@ -1,15 +0,0 @@
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
from core.models.notes import Notes
|
||||
|
||||
|
||||
class AddNoteForm(CommonModelForm):
|
||||
|
||||
prefix = 'note'
|
||||
|
||||
class Meta:
|
||||
model = Notes
|
||||
fields = [
|
||||
'note'
|
||||
]
|
@ -1,104 +0,0 @@
|
||||
from django import forms
|
||||
from django.db.models import Q
|
||||
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
|
||||
|
||||
class CommonModelForm(forms.ModelForm):
|
||||
""" Abstract Form class for form inclusion
|
||||
|
||||
This class exists so that common functions can be conducted against forms as they are loaded.
|
||||
"""
|
||||
|
||||
organization_field: str = 'organization'
|
||||
""" Organization Field
|
||||
|
||||
Name of the field that contains Organizations.
|
||||
|
||||
This field will be filtered to those that the user is part of.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Form initialization.
|
||||
|
||||
Initialize the form using the super classes first then continue to initialize the form using logic
|
||||
contained within this method.
|
||||
|
||||
## Tenancy Objects
|
||||
|
||||
Fields that contain an attribute called `organization` will have the objects filtered to
|
||||
the organizations the user is part of. If the object has `is_global=True`, that object will not be
|
||||
filtered out.
|
||||
|
||||
|
||||
!!! danger "Requirement"
|
||||
This method may be overridden however must still be called from the overriding function. i.e. `super().__init__(*args, **kwargs)`
|
||||
"""
|
||||
|
||||
user = kwargs.pop('user', None)
|
||||
|
||||
user_organizations: list([str]) = []
|
||||
user_organizations_id: list(int()) = []
|
||||
|
||||
for team_user in TeamUsers.objects.filter(user=user):
|
||||
|
||||
if team_user.team.organization.name not in user_organizations:
|
||||
|
||||
|
||||
user_organizations += [ team_user.team.organization.name ]
|
||||
user_organizations_id += [ team_user.team.organization.id ]
|
||||
|
||||
new_kwargs: dict = {}
|
||||
|
||||
for key, value in kwargs.items():
|
||||
|
||||
if key != 'user':
|
||||
|
||||
new_kwargs.update({key: value})
|
||||
|
||||
super().__init__(*args, **new_kwargs)
|
||||
|
||||
|
||||
if len(user_organizations_id) > 0:
|
||||
|
||||
for field_name in self.fields:
|
||||
|
||||
field = self.fields[field_name]
|
||||
|
||||
if hasattr(field, 'queryset'):
|
||||
|
||||
if hasattr(field.queryset.model, 'organization'):
|
||||
|
||||
if hasattr(field.queryset.model, 'is_global'):
|
||||
|
||||
if field.queryset.model.is_global is not None:
|
||||
|
||||
self.fields[field_name].queryset = field.queryset.filter(
|
||||
Q(organization__in=user_organizations_id)
|
||||
|
|
||||
Q(is_global = True)
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
self.fields[field_name].queryset = field.queryset.filter(
|
||||
Q(organization__in=user_organizations_id)
|
||||
)
|
||||
|
||||
|
||||
if self.Meta.fields:
|
||||
|
||||
if self.organization_field in self.Meta.fields:
|
||||
|
||||
self.fields[self.organization_field].queryset = self.fields[self.organization_field].queryset.filter(
|
||||
Q(id__in=user_organizations_id)
|
||||
|
|
||||
Q(manager=user)
|
||||
)
|
||||
|
||||
if hasattr(self, 'instance'):
|
||||
|
||||
self.model_name_plural = self.instance._meta.verbose_name_plural
|
@ -1,90 +0,0 @@
|
||||
from django import forms
|
||||
from django.urls import reverse
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
from core.models.manufacturer import Manufacturer
|
||||
|
||||
from settings.forms.admin_settings_global import AdminGlobalModels
|
||||
|
||||
|
||||
|
||||
class ManufacturerForm(
|
||||
AdminGlobalModels,
|
||||
CommonModelForm
|
||||
):
|
||||
|
||||
class Meta:
|
||||
|
||||
fields = [
|
||||
'name',
|
||||
'slug',
|
||||
'id',
|
||||
'organization',
|
||||
'is_global',
|
||||
'model_notes',
|
||||
]
|
||||
|
||||
model = Manufacturer
|
||||
|
||||
|
||||
|
||||
class DetailForm(ManufacturerForm):
|
||||
|
||||
tabs: dict = {
|
||||
"details": {
|
||||
"name": "Details",
|
||||
"slug": "details",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "double",
|
||||
"left": [
|
||||
'name',
|
||||
'slug',
|
||||
'organization',
|
||||
'is_global',
|
||||
'c_created',
|
||||
'c_modified',
|
||||
],
|
||||
"right": [
|
||||
'model_notes',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
# "notes": {
|
||||
# "name": "Notes",
|
||||
# "slug": "notes",
|
||||
# "sections": []
|
||||
# }
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
self.fields['c_created'] = forms.DateTimeField(
|
||||
label = 'Created',
|
||||
input_formats=settings.DATETIME_FORMAT,
|
||||
disabled = True,
|
||||
initial = self.instance.created,
|
||||
)
|
||||
|
||||
self.fields['c_modified'] = forms.DateTimeField(
|
||||
label = 'Modified',
|
||||
input_formats=settings.DATETIME_FORMAT,
|
||||
disabled = True,
|
||||
initial = self.instance.modified,
|
||||
)
|
||||
|
||||
|
||||
self.tabs['details'].update({
|
||||
"edit_url": reverse('Settings:_manufacturer_change', args=(self.instance.pk,))
|
||||
})
|
||||
|
||||
self.url_index_view = reverse('Settings:_manufacturers')
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
from django import forms
|
||||
from django.db.models import Q
|
||||
from django.forms import ValidationError
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
|
||||
from core.models.ticket.ticket import RelatedTickets
|
||||
|
||||
|
||||
class RelatedTicketForm(CommonModelForm):
|
||||
|
||||
prefix = 'ticket'
|
||||
|
||||
class Meta:
|
||||
model = RelatedTickets
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['from_ticket_id'].widget = self.fields['from_ticket_id'].hidden_widget()
|
||||
|
||||
|
||||
def clean(self):
|
||||
|
||||
cleaned_data = super().clean()
|
||||
|
||||
return cleaned_data
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
|
||||
is_valid = super().is_valid()
|
||||
|
||||
check_db = self.Meta.model.objects.filter(
|
||||
to_ticket_id = self.cleaned_data['to_ticket_id'].id,
|
||||
from_ticket_id = self.cleaned_data['from_ticket_id'].id,
|
||||
)
|
||||
|
||||
check_db_inverse = self.Meta.model.objects.filter(
|
||||
to_ticket_id = self.cleaned_data['from_ticket_id'].id,
|
||||
from_ticket_id = self.cleaned_data['to_ticket_id'].id,
|
||||
)
|
||||
|
||||
if check_db.count() > 0 or check_db_inverse.count() > 0:
|
||||
|
||||
raise ValidationError(f"Ticket is already related to #{self.cleaned_data['to_ticket_id'].id}")
|
||||
|
||||
is_valid = False
|
||||
|
||||
|
||||
return is_valid
|
@ -1,249 +0,0 @@
|
||||
from django import forms
|
||||
from django.db.models import Q
|
||||
from django.forms import ValidationError
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
from core.forms.validate_ticket import TicketValidation
|
||||
|
||||
from core.models.ticket.ticket import Ticket, RelatedTickets
|
||||
|
||||
|
||||
|
||||
class TicketForm(
|
||||
CommonModelForm,
|
||||
TicketValidation,
|
||||
):
|
||||
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
|
||||
self.request = request
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['planned_start_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local', 'format': "%Y-%m-%dT%H:%M"})
|
||||
self.fields['planned_start_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['planned_start_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['planned_finish_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local'})
|
||||
self.fields['planned_finish_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['planned_finish_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['real_start_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local'})
|
||||
self.fields['real_start_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['real_start_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['real_finish_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local'})
|
||||
self.fields['real_finish_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['real_finish_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['description'].widget.attrs = {'style': "height: 800px; width: 900px"}
|
||||
|
||||
self.fields['opened_by'].initial = kwargs['user'].pk
|
||||
self.fields['opened_by'].widget = self.fields['opened_by'].hidden_widget()
|
||||
|
||||
self.fields['ticket_type'].widget = self.fields['ticket_type'].hidden_widget()
|
||||
|
||||
self.fields['organization'].initial = self.initial['organization']
|
||||
|
||||
if self.instance.pk is not None:
|
||||
|
||||
del self.fields['organization']
|
||||
|
||||
if self.instance.project is not None:
|
||||
|
||||
self.fields['milestone'].queryset = self.fields['milestone'].queryset.filter(
|
||||
project=self.instance.project
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
self.fields['milestone'].queryset = self.fields['milestone'].queryset.filter(
|
||||
id=0
|
||||
)
|
||||
|
||||
|
||||
original_fields = self.fields.copy()
|
||||
ticket_type = []
|
||||
|
||||
if kwargs['initial']['type_ticket'] == 'request':
|
||||
|
||||
ticket_type = self.Meta.model.fields_itsm_request
|
||||
|
||||
self.fields['status'].choices = self.Meta.model.TicketStatus.Request
|
||||
|
||||
self.fields['ticket_type'].initial = '1'
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
request=True
|
||||
)
|
||||
|
||||
elif kwargs['initial']['type_ticket'] == 'incident':
|
||||
|
||||
ticket_type = self.Meta.model.fields_itsm_incident
|
||||
|
||||
self.fields['status'].choices = self.Meta.model.TicketStatus.Incident
|
||||
|
||||
self.fields['ticket_type'].initial = self.Meta.model.TicketType.INCIDENT.value
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
incident=True
|
||||
)
|
||||
|
||||
elif kwargs['initial']['type_ticket'] == 'problem':
|
||||
|
||||
ticket_type = self.Meta.model.fields_itsm_problem
|
||||
|
||||
self.fields['status'].choices = self.Meta.model.TicketStatus.Problem
|
||||
|
||||
self.fields['ticket_type'].initial = self.Meta.model.TicketType.PROBLEM.value
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
problem=True
|
||||
)
|
||||
elif kwargs['initial']['type_ticket'] == 'change':
|
||||
|
||||
ticket_type = self.Meta.model.fields_itsm_change
|
||||
|
||||
self.fields['status'].choices = self.Meta.model.TicketStatus.Change
|
||||
|
||||
self.fields['ticket_type'].initial = self.Meta.model.TicketType.CHANGE.value
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
change=True
|
||||
)
|
||||
elif kwargs['initial']['type_ticket'] == 'issue':
|
||||
|
||||
ticket_type = self.Meta.model.fields_git_issue
|
||||
|
||||
self.fields['status'].choices = self.Meta.model.TicketStatus.Git
|
||||
|
||||
self.fields['ticket_type'].initial = self.Meta.model.TicketType.ISSUE.value
|
||||
|
||||
elif kwargs['initial']['type_ticket'] == 'merge':
|
||||
|
||||
ticket_type = self.Meta.model.fields_git_merge
|
||||
|
||||
self.fields['status'].choices = self.Meta.model.TicketStatus.Git
|
||||
|
||||
self.fields['ticket_type'].initial = self.Meta.model.TicketType.MERGE_REQUEST.value
|
||||
|
||||
elif kwargs['initial']['type_ticket'] == 'project_task':
|
||||
|
||||
ticket_type = self.Meta.model.fields_project_task
|
||||
|
||||
self.fields['status'].choices = self.Meta.model.TicketStatus.ProjectTask
|
||||
|
||||
self._project: int = kwargs['initial']['project']
|
||||
|
||||
self.fields['project'].initial = self._project
|
||||
self.fields['project'].widget = self.fields['project'].hidden_widget()
|
||||
|
||||
self.fields['ticket_type'].initial = self.Meta.model.TicketType.PROJECT_TASK.value
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
project_task=True
|
||||
)
|
||||
|
||||
if kwargs['user'].is_superuser:
|
||||
|
||||
ticket_type += self.Meta.model.tech_fields
|
||||
|
||||
self.ticket_type_fields = ticket_type
|
||||
|
||||
fields_allowed_by_permission = self.get_fields_allowed_by_permission
|
||||
|
||||
allowed_ticket_fields: list = []
|
||||
|
||||
for field in fields_allowed_by_permission: # Remove fields not intended for the ticket type
|
||||
|
||||
|
||||
if field in ticket_type:
|
||||
|
||||
allowed_ticket_fields = allowed_ticket_fields + [ field ]
|
||||
|
||||
|
||||
for field in original_fields: # Remove fields user cant edit unless field is hidden
|
||||
|
||||
if (
|
||||
(
|
||||
field not in allowed_ticket_fields and not self.fields[field].widget.is_hidden
|
||||
)
|
||||
or
|
||||
field not in ticket_type
|
||||
):
|
||||
|
||||
# self.fields[field].widget = self.fields[field].hidden_widget()
|
||||
del self.fields[field]
|
||||
|
||||
|
||||
def clean(self):
|
||||
|
||||
cleaned_data = super().clean()
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
|
||||
is_valid = super().is_valid()
|
||||
|
||||
self.validate_ticket()
|
||||
|
||||
if self._ticket_type == 'change':
|
||||
|
||||
self.validate_change_ticket()
|
||||
|
||||
elif self._ticket_type == 'incident':
|
||||
|
||||
self.validate_incident_ticket()
|
||||
|
||||
elif self._ticket_type == 'issue':
|
||||
|
||||
# self.validate_issue_ticket()
|
||||
raise ValidationError(
|
||||
'This Ticket type is not yet available'
|
||||
)
|
||||
|
||||
elif self._ticket_type == 'merge_request':
|
||||
|
||||
# self.validate_merge_request_ticket()
|
||||
raise ValidationError(
|
||||
'This Ticket type is not yet available'
|
||||
)
|
||||
|
||||
elif self._ticket_type == 'problem':
|
||||
|
||||
self.validate_problem_ticket()
|
||||
|
||||
elif self._ticket_type == 'project_task':
|
||||
|
||||
self.validate_project_task_ticket()
|
||||
|
||||
elif self._ticket_type == 'request':
|
||||
|
||||
self.validate_request_ticket()
|
||||
|
||||
else:
|
||||
|
||||
raise ValidationError('Ticket Type must be set')
|
||||
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
|
||||
class DetailForm(CommonModelForm):
|
||||
|
||||
prefix = 'ticket'
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields = '__all__'
|
@ -1,120 +0,0 @@
|
||||
from django import forms
|
||||
from django.forms import ValidationError
|
||||
from django.urls import reverse
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
from core.models.ticket.ticket_category import TicketCategory
|
||||
|
||||
|
||||
|
||||
class TicketCategoryForm(CommonModelForm):
|
||||
|
||||
|
||||
class Meta:
|
||||
|
||||
fields = '__all__'
|
||||
|
||||
model = TicketCategory
|
||||
|
||||
prefix = 'ticket_category'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['parent'].queryset = self.fields['parent'].queryset.exclude(
|
||||
id=self.instance.pk
|
||||
)
|
||||
|
||||
|
||||
def clean(self):
|
||||
|
||||
cleaned_data = super().clean()
|
||||
|
||||
pk = self.instance.id
|
||||
|
||||
parent = cleaned_data.get("parent")
|
||||
|
||||
if pk:
|
||||
|
||||
if parent == pk:
|
||||
|
||||
raise ValidationError("Category can't have itself as its parent category")
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
|
||||
class DetailForm(TicketCategoryForm):
|
||||
|
||||
|
||||
tabs: dict = {
|
||||
"details": {
|
||||
"name": "Details",
|
||||
"slug": "details",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "double",
|
||||
"left": [
|
||||
'parent',
|
||||
'name',
|
||||
'runbook',
|
||||
'organization',
|
||||
'c_created',
|
||||
'c_modified'
|
||||
],
|
||||
"right": [
|
||||
'model_notes',
|
||||
]
|
||||
},
|
||||
{
|
||||
"layout": "double",
|
||||
"name": "Ticket Types",
|
||||
"left": [
|
||||
'change',
|
||||
'problem',
|
||||
'request'
|
||||
],
|
||||
"right": [
|
||||
'incident',
|
||||
'project_task'
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
"notes": {
|
||||
"name": "Notes",
|
||||
"slug": "notes",
|
||||
"sections": []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
self.fields['c_created'] = forms.DateTimeField(
|
||||
label = 'Created',
|
||||
input_formats=settings.DATETIME_FORMAT,
|
||||
disabled = True,
|
||||
initial = self.instance.created,
|
||||
)
|
||||
|
||||
self.fields['c_modified'] = forms.DateTimeField(
|
||||
label = 'Modified',
|
||||
input_formats=settings.DATETIME_FORMAT,
|
||||
disabled = True,
|
||||
initial = self.instance.modified,
|
||||
)
|
||||
|
||||
|
||||
self.tabs['details'].update({
|
||||
"edit_url": reverse('Settings:_ticket_category_change', kwargs={'pk': self.instance.pk})
|
||||
})
|
||||
|
||||
self.url_index_view = reverse('Settings:_ticket_categories')
|
||||
|
@ -1,163 +0,0 @@
|
||||
from django import forms
|
||||
from django.db.models import Q
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
from core.forms.validate_ticket_comment import TicketCommentValidation
|
||||
|
||||
from core.models.ticket.ticket_comment import TicketComment
|
||||
|
||||
|
||||
|
||||
class CommentForm(
|
||||
CommonModelForm,
|
||||
TicketCommentValidation
|
||||
):
|
||||
|
||||
prefix = 'ticket'
|
||||
|
||||
class Meta:
|
||||
model = TicketComment
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
|
||||
self.request = request
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._ticket_organization = self.fields['ticket'].queryset.model.objects.get(pk=int(self.initial['ticket'])).organization
|
||||
|
||||
self._ticket_type = kwargs['initial']['type_ticket']
|
||||
|
||||
if 'qs_comment_type' in kwargs['initial']:
|
||||
|
||||
self._comment_type = kwargs['initial']['qs_comment_type']
|
||||
|
||||
else:
|
||||
|
||||
self._comment_type = str(self.instance.get_comment_type_display()).lower()
|
||||
|
||||
self.ticket_comment_permissions
|
||||
|
||||
|
||||
self.fields['planned_start_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local', 'format': "%Y-%m-%dT%H:%M"})
|
||||
self.fields['planned_start_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['planned_start_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['planned_finish_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local'})
|
||||
self.fields['planned_finish_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['planned_finish_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['real_start_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local'})
|
||||
self.fields['real_start_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['real_start_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['real_finish_date'].widget = forms.widgets.DateTimeInput(attrs={'type': 'datetime-local'})
|
||||
self.fields['real_finish_date'].input_formats = settings.DATETIME_FORMAT
|
||||
self.fields['real_finish_date'].format="%Y-%m-%dT%H:%M"
|
||||
|
||||
self.fields['body'].widget.attrs = {'style': "height: 800px; width: 900px"}
|
||||
|
||||
self.fields['duration'].widget = self.fields['duration'].hidden_widget()
|
||||
|
||||
self.fields['user'].initial = kwargs['user'].pk
|
||||
self.fields['user'].widget = self.fields['user'].hidden_widget()
|
||||
|
||||
self.fields['ticket'].widget = self.fields['ticket'].hidden_widget()
|
||||
|
||||
self.fields['parent'].widget = self.fields['parent'].hidden_widget()
|
||||
self.fields['comment_type'].widget = self.fields['comment_type'].hidden_widget()
|
||||
|
||||
if not( self._has_import_permission or self._has_triage_permission or request.user.is_superuser ):
|
||||
|
||||
self.fields['source'].initial = TicketComment.CommentSource.HELPDESK
|
||||
|
||||
self.fields['source'].widget = self.fields['source'].hidden_widget()
|
||||
|
||||
else:
|
||||
|
||||
self.fields['source'].initial = TicketComment.CommentSource.DIRECT
|
||||
|
||||
|
||||
|
||||
|
||||
if self._comment_type == 'task':
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.TASK
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
task = True
|
||||
)
|
||||
|
||||
elif self._comment_type == 'comment':
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.COMMENT
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
comment = True
|
||||
)
|
||||
|
||||
elif self._comment_type == 'solution':
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.SOLUTION
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
solution = True
|
||||
)
|
||||
|
||||
elif self._comment_type == 'notification':
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.NOTIFICATION
|
||||
|
||||
self.fields['category'].queryset = self.fields['category'].queryset.filter(
|
||||
notification = True
|
||||
)
|
||||
|
||||
|
||||
allowed_fields = self.fields_allowed
|
||||
|
||||
original_fields = self.fields.copy()
|
||||
|
||||
|
||||
for field in original_fields:
|
||||
|
||||
if field not in allowed_fields and not self.fields[field].widget.is_hidden:
|
||||
|
||||
del self.fields[field]
|
||||
|
||||
|
||||
def clean(self):
|
||||
|
||||
cleaned_data = super().clean()
|
||||
|
||||
return cleaned_data
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
|
||||
is_valid = super().is_valid()
|
||||
|
||||
validate_ticket_comment: bool = self.validate_ticket_comment()
|
||||
|
||||
if not validate_ticket_comment:
|
||||
|
||||
is_valid = validate_ticket_comment
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
|
||||
class DetailForm(CommentForm):
|
||||
|
||||
prefix = 'ticket'
|
||||
|
||||
class Meta:
|
||||
model = TicketComment
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
@ -1,119 +0,0 @@
|
||||
from django import forms
|
||||
from django.forms import ValidationError
|
||||
from django.urls import reverse
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
from core.models.ticket.ticket_comment_category import TicketCommentCategory
|
||||
|
||||
|
||||
|
||||
class TicketCommentCategoryForm(CommonModelForm):
|
||||
|
||||
|
||||
class Meta:
|
||||
|
||||
fields = '__all__'
|
||||
|
||||
model = TicketCommentCategory
|
||||
|
||||
prefix = 'ticket_comment_category'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['parent'].queryset = self.fields['parent'].queryset.exclude(
|
||||
id=self.instance.pk
|
||||
)
|
||||
|
||||
|
||||
def clean(self):
|
||||
|
||||
cleaned_data = super().clean()
|
||||
|
||||
pk = self.instance.id
|
||||
|
||||
parent = cleaned_data.get("parent")
|
||||
|
||||
if pk:
|
||||
|
||||
if parent == pk:
|
||||
|
||||
raise ValidationError("Category can't have itself as its parent category")
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
|
||||
class DetailForm(TicketCommentCategoryForm):
|
||||
|
||||
|
||||
tabs: dict = {
|
||||
"details": {
|
||||
"name": "Details",
|
||||
"slug": "details",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "double",
|
||||
"left": [
|
||||
'parent',
|
||||
'name',
|
||||
'runbook',
|
||||
'organization',
|
||||
'c_created',
|
||||
'c_modified'
|
||||
],
|
||||
"right": [
|
||||
'model_notes',
|
||||
]
|
||||
},
|
||||
{
|
||||
"layout": "double",
|
||||
"name": "Comment Types",
|
||||
"left": [
|
||||
'comment',
|
||||
'solution'
|
||||
],
|
||||
"right": [
|
||||
'notification',
|
||||
'task'
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
"notes": {
|
||||
"name": "Notes",
|
||||
"slug": "notes",
|
||||
"sections": []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
self.fields['c_created'] = forms.DateTimeField(
|
||||
label = 'Created',
|
||||
input_formats=settings.DATETIME_FORMAT,
|
||||
disabled = True,
|
||||
initial = self.instance.created,
|
||||
)
|
||||
|
||||
self.fields['c_modified'] = forms.DateTimeField(
|
||||
label = 'Modified',
|
||||
input_formats=settings.DATETIME_FORMAT,
|
||||
disabled = True,
|
||||
initial = self.instance.modified,
|
||||
)
|
||||
|
||||
|
||||
self.tabs['details'].update({
|
||||
"edit_url": reverse('Settings:_ticket_comment_category_change', kwargs={'pk': self.instance.pk})
|
||||
})
|
||||
|
||||
self.url_index_view = reverse('Settings:_ticket_comment_categories')
|
||||
|
@ -1,26 +0,0 @@
|
||||
from django import forms
|
||||
from django.db.models import Q
|
||||
from django.forms import ValidationError
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from core.forms.common import CommonModelForm
|
||||
|
||||
from core.models.ticket.ticket_linked_items import TicketLinkedItem
|
||||
|
||||
|
||||
class TicketLinkedItemForm(CommonModelForm):
|
||||
|
||||
prefix = 'ticket_linked_item'
|
||||
|
||||
class Meta:
|
||||
model = TicketLinkedItem
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['organization'].widget = self.fields['organization'].hidden_widget()
|
||||
self.fields['ticket'].widget = self.fields['ticket'].hidden_widget()
|
@ -1,681 +0,0 @@
|
||||
from django.core.exceptions import PermissionDenied, ValidationError
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from access.mixin import OrganizationMixin
|
||||
|
||||
|
||||
class TicketValidation(
|
||||
OrganizationMixin,
|
||||
):
|
||||
"""Ticket Form/Serializer Validation
|
||||
|
||||
Validate a ticket form or api viewset
|
||||
|
||||
## Class requirements
|
||||
|
||||
- attribute `ticket_type_fields` is set to a list of fields for the ticket type
|
||||
|
||||
- attribute `ticket_type` is set to a string value (lowercase) of the ticket type
|
||||
|
||||
Raises:
|
||||
PermissionDenied: User has no allowable fields to edit
|
||||
PermissionDenied: User is lacking permission to edit a field
|
||||
serializers.ValidationError: Status field has a value set that does not meet the ticket type
|
||||
ValidationError: Status field has a value set that does not meet the ticket type
|
||||
|
||||
"""
|
||||
|
||||
original_object = None
|
||||
|
||||
add_fields: list = [
|
||||
'title',
|
||||
'description',
|
||||
'urgency',
|
||||
'organization'
|
||||
]
|
||||
|
||||
change_fields: list = []
|
||||
|
||||
delete_fields: list = [
|
||||
'is_deleted',
|
||||
]
|
||||
|
||||
import_fields: list = [
|
||||
'assigned_users',
|
||||
'assigned_teams',
|
||||
'category',
|
||||
'created',
|
||||
'date_closed',
|
||||
'estimate',
|
||||
'external_ref',
|
||||
'external_system',
|
||||
'status',
|
||||
'impact',
|
||||
'opened_by',
|
||||
'planned_start_date',
|
||||
'planned_finish_date',
|
||||
'priority',
|
||||
'project',
|
||||
'milestone',
|
||||
'real_start_date',
|
||||
'real_finish_date',
|
||||
'subscribed_users',
|
||||
'subscribed_teams',
|
||||
'ticket_type',
|
||||
]
|
||||
|
||||
triage_fields: list = [
|
||||
'category',
|
||||
'assigned_users',
|
||||
'assigned_teams',
|
||||
'estimate',
|
||||
'status',
|
||||
'impact',
|
||||
'opened_by',
|
||||
'planned_start_date',
|
||||
'planned_finish_date',
|
||||
'priority',
|
||||
'project',
|
||||
'milestone',
|
||||
'real_start_date',
|
||||
'real_finish_date',
|
||||
'subscribed_users',
|
||||
'subscribed_teams',
|
||||
]
|
||||
|
||||
|
||||
def combined_validation_error(self, message:str, code:str = None) -> None:
|
||||
|
||||
if 'serializers' in self.Meta.__module__:
|
||||
|
||||
raise serializers.ValidationError(
|
||||
detail = message,
|
||||
code = code
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
raise ValidationError(
|
||||
message = message,
|
||||
code = code
|
||||
)
|
||||
|
||||
|
||||
@property
|
||||
def get_fields_allowed_by_permission(self) -> list(str()):
|
||||
"""Obtain Fields that the user can edit
|
||||
|
||||
First obtain the users organization. As this can be found in multiple
|
||||
locations, first check and fetch from the existing ticket. If this is
|
||||
a new ticket, the organization should have been supplied, so use that.
|
||||
|
||||
Check the permission after building the required permission using the
|
||||
ticket type.
|
||||
|
||||
|
||||
Returns:
|
||||
list(str()): Fields the user can edit.
|
||||
"""
|
||||
|
||||
if hasattr(self, '_fields_allowed_by_permission'):
|
||||
|
||||
return self._fields_allowed_by_permission
|
||||
|
||||
if not hasattr(self, '_ticket_type'):
|
||||
|
||||
self._ticket_type = self.initial['type_ticket']
|
||||
|
||||
|
||||
fields_allowed: list = []
|
||||
|
||||
ticket_organization = None
|
||||
|
||||
if self.instance is not None:
|
||||
|
||||
if self.instance.pk:
|
||||
|
||||
ticket_organization = self.instance.organization
|
||||
|
||||
|
||||
if ticket_organization is None:
|
||||
|
||||
ticket_organization = self.initial['organization']
|
||||
|
||||
if ticket_organization is None:
|
||||
|
||||
if 'organization' in self.data:
|
||||
|
||||
ticket_organization = self.fields['organization'].queryset.model.objects.get(pk=self.data['organization'])
|
||||
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=ticket_organization.id,
|
||||
permissions_required = [ 'core.add_ticket_'+ self._ticket_type ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = self.add_fields
|
||||
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=ticket_organization.id,
|
||||
permissions_required = [ 'core.change_ticket_'+ self._ticket_type ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
if len(fields_allowed) == 0:
|
||||
|
||||
fields_allowed = self.add_fields + self.change_fields
|
||||
|
||||
else:
|
||||
|
||||
fields_allowed = fields_allowed + self.change_fields
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=ticket_organization.id,
|
||||
permissions_required = [ 'core.delete_ticket_'+ self._ticket_type ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = fields_allowed + self.delete_fields
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=ticket_organization.id,
|
||||
permissions_required = [ 'core.import_ticket_'+ self._ticket_type ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
if hasattr(self, 'serializer_choice_field'):
|
||||
|
||||
fields_allowed = fields_allowed + self.import_fields
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=ticket_organization.id,
|
||||
permissions_required = [ 'core.triage_ticket_'+ self._ticket_type ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = fields_allowed + self.triage_fields
|
||||
|
||||
if self.request.user.is_superuser:
|
||||
|
||||
all_fields: list = self.add_fields
|
||||
all_fields = all_fields + self.change_fields
|
||||
all_fields = all_fields + self.delete_fields
|
||||
all_fields = all_fields + self.import_fields
|
||||
all_fields = all_fields + self.triage_fields
|
||||
|
||||
fields_allowed = fields_allowed + all_fields
|
||||
|
||||
self._fields_allowed_by_permission = fields_allowed
|
||||
|
||||
return fields_allowed
|
||||
|
||||
|
||||
@property
|
||||
def get_user_changed_data(self) -> dict:
|
||||
"""Create an object with the user 'changed' data.
|
||||
|
||||
Due to forms having fields deleted, this function is required
|
||||
as attribute `cleaned_data` no longer functions per normal.
|
||||
|
||||
Returns:
|
||||
_user_changed_data (dict): Changed data.
|
||||
"""
|
||||
|
||||
if hasattr(self, '_user_changed_data'):
|
||||
|
||||
return self._user_changed_data
|
||||
|
||||
changed_data: dict = {}
|
||||
|
||||
for field in self.get_user_changed_fields:
|
||||
|
||||
if hasattr(self.Meta.model, field):
|
||||
|
||||
changed_data.update({
|
||||
field: self.request.POST.dict()[field]
|
||||
})
|
||||
|
||||
|
||||
if len(changed_data) > 0:
|
||||
|
||||
self._user_changed_data = changed_data
|
||||
|
||||
return changed_data
|
||||
|
||||
|
||||
@property
|
||||
def get_user_changed_fields(self) -> list(str()):
|
||||
"""List of fields the user changed.
|
||||
|
||||
This data is sourced from the HTTP/POST data.
|
||||
|
||||
Returns:
|
||||
list: All of the fields that have changed.
|
||||
"""
|
||||
|
||||
if hasattr(self, '_user_changed_fields'):
|
||||
|
||||
return self._user_changed_fields
|
||||
|
||||
changed_data: list = []
|
||||
|
||||
changed_data_exempt = [
|
||||
'_state',
|
||||
'csrfmiddlewaretoken',
|
||||
'ticket_comments',
|
||||
'url',
|
||||
]
|
||||
|
||||
post_data: dict = self.request.POST.dict().copy()
|
||||
|
||||
for field in post_data:
|
||||
|
||||
if hasattr(self.Meta.model, field):
|
||||
|
||||
changed_data = changed_data + [ field ]
|
||||
|
||||
|
||||
if len(changed_data) > 0:
|
||||
|
||||
self._user_changed_fields = changed_data
|
||||
|
||||
return changed_data
|
||||
|
||||
|
||||
@property
|
||||
def validate_field_permission(self):
|
||||
""" Check field permissions
|
||||
|
||||
Users can't edit all fields. They can only adjust fields that they
|
||||
have the permissions to adjust.
|
||||
|
||||
## Required fields
|
||||
|
||||
A field marked as required when the instance has no pk, the field will have
|
||||
it's permission marked as allowed. This is not the case for items thaat are being
|
||||
edited, i.e. have a pk.
|
||||
|
||||
Raises:
|
||||
ValidationError: Access Denied when user has no ticket permissions assigned
|
||||
ValidationError: User tried to edit a field they dont have permission to edit.
|
||||
"""
|
||||
|
||||
fields_allowed = self.get_fields_allowed_by_permission
|
||||
|
||||
if len(fields_allowed) == 0:
|
||||
|
||||
self.combined_validation_error('Access Denied to all fields', code='access_denied_all_fields')
|
||||
|
||||
|
||||
for field in self.get_user_changed_fields:
|
||||
|
||||
allowed: bool = False
|
||||
|
||||
if (
|
||||
field in self.fields
|
||||
and field in self.ticket_type_fields
|
||||
and (
|
||||
field in fields_allowed
|
||||
)
|
||||
):
|
||||
|
||||
allowed = True
|
||||
|
||||
if hasattr(self.instance, 'pk'):
|
||||
|
||||
if (
|
||||
field in self.fields
|
||||
and field in self.ticket_type_fields
|
||||
and self.instance.pk is None
|
||||
):
|
||||
|
||||
if self.fields[field].required:
|
||||
|
||||
allowed = True
|
||||
|
||||
elif self.instance is None:
|
||||
|
||||
if self.fields[field].required:
|
||||
|
||||
allowed = True
|
||||
|
||||
|
||||
if not allowed:
|
||||
|
||||
if (
|
||||
self.field_edited(field)
|
||||
or (
|
||||
field not in fields_allowed
|
||||
and hasattr(self.Meta.model, field)
|
||||
)
|
||||
):
|
||||
|
||||
self.combined_validation_error(
|
||||
f'cant edit field: {field}',
|
||||
code=f'cant_edit_field_{field}',
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def field_edited(self, field:str) -> bool:
|
||||
|
||||
if hasattr(self, 'cleaned_data'): # initial avail in ui
|
||||
|
||||
initial_data: dict = self.initial
|
||||
changed_data: dict = self.get_user_changed_data
|
||||
|
||||
elif hasattr(self, 'validated_data'): # API
|
||||
|
||||
initial_data:dict = self.instance.__dict__
|
||||
changed_data: dict = self.validated_data
|
||||
|
||||
if field in initial_data:
|
||||
|
||||
value = initial_data[field]
|
||||
|
||||
elif str(field) + '_id' in initial_data:
|
||||
|
||||
value = initial_data[str(field) + '_id']
|
||||
|
||||
else:
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if field in changed_data:
|
||||
|
||||
if changed_data[field] == value:
|
||||
|
||||
return False
|
||||
|
||||
if hasattr(changed_data[field], 'id'):
|
||||
|
||||
if value is None:
|
||||
|
||||
return True
|
||||
|
||||
if int(value) == changed_data[field].id:
|
||||
|
||||
return False
|
||||
|
||||
else:
|
||||
|
||||
val = value
|
||||
|
||||
if value is None:
|
||||
|
||||
return True
|
||||
|
||||
if type(changed_data[field]) is int:
|
||||
|
||||
val = int(value)
|
||||
|
||||
elif type(changed_data[field]) is bool:
|
||||
|
||||
val = bool(value)
|
||||
|
||||
elif type(changed_data[field]) is str:
|
||||
|
||||
val = str(value)
|
||||
|
||||
|
||||
if val == changed_data[field]:
|
||||
|
||||
return False
|
||||
|
||||
else:
|
||||
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def validate_field_milestone(self):
|
||||
|
||||
is_valid: bool = False
|
||||
|
||||
if self.instance is not None:
|
||||
|
||||
if self.instance.milestone is None:
|
||||
|
||||
return True
|
||||
|
||||
else:
|
||||
|
||||
if self.instance.project is None:
|
||||
|
||||
self.combined_validation_error(
|
||||
f'Milestones require a project',
|
||||
code=f'milestone_requires_project',
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
if self.instance.project.id == self.instance.milestone.project.id:
|
||||
|
||||
return True
|
||||
|
||||
else:
|
||||
|
||||
self.combined_validation_error(
|
||||
f'Milestone must be from the same project',
|
||||
code=f'milestone_same_project',
|
||||
)
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
def validate_field_organization(self) -> bool:
|
||||
"""Check `organization field`
|
||||
|
||||
Raises:
|
||||
ValidationError: user tried to change the organization
|
||||
|
||||
Returns:
|
||||
True (bool): OK
|
||||
False (bool): User tried to edit the organization
|
||||
"""
|
||||
|
||||
is_valid: bool = True
|
||||
|
||||
if self.instance is not None:
|
||||
|
||||
if self.instance.pk is not None:
|
||||
|
||||
if 'organization' in self.get_user_changed_fields:
|
||||
|
||||
if self.field_edited('organization'):
|
||||
|
||||
is_valid = False
|
||||
|
||||
self.combined_validation_error(
|
||||
f'cant edit field: organization',
|
||||
code=f'cant_edit_field_organization',
|
||||
)
|
||||
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
def validate_field_status(self):
|
||||
"""Validate status field
|
||||
|
||||
Ticket status depends upon ticket type.
|
||||
Ensure that the corrent status is used.
|
||||
"""
|
||||
|
||||
is_valid = False
|
||||
|
||||
if not hasattr(self, '_ticket_type'):
|
||||
|
||||
self._ticket_type = self.initial['type_ticket']
|
||||
|
||||
try:
|
||||
|
||||
if hasattr(self, 'cleaned_data'):
|
||||
|
||||
field = self.cleaned_data['status']
|
||||
|
||||
else:
|
||||
|
||||
field = self.validated_data['status']
|
||||
|
||||
except KeyError:
|
||||
|
||||
# field = self.fields['status'].default.value
|
||||
field = getattr(self.Meta.model, 'status').field.default.value
|
||||
|
||||
|
||||
if self._ticket_type == 'request':
|
||||
|
||||
if field in self.Meta.model.TicketStatus.Request._value2member_map_:
|
||||
|
||||
is_valid = True
|
||||
|
||||
elif self._ticket_type == 'incident':
|
||||
|
||||
if field in self.Meta.model.TicketStatus.Incident._value2member_map_:
|
||||
|
||||
is_valid = True
|
||||
|
||||
elif self._ticket_type == 'problem':
|
||||
|
||||
if field in self.Meta.model.TicketStatus.Problem._value2member_map_:
|
||||
|
||||
is_valid = True
|
||||
|
||||
elif self._ticket_type == 'change':
|
||||
|
||||
if field in self.Meta.model.TicketStatus.Change._value2member_map_:
|
||||
|
||||
is_valid = True
|
||||
|
||||
elif self._ticket_type == 'issue':
|
||||
|
||||
if field in self.Meta.model.TicketStatus.Issue._value2member_map_:
|
||||
|
||||
is_valid = True
|
||||
|
||||
elif self._ticket_type == 'merge':
|
||||
|
||||
if field in self.Meta.model.TicketStatus.Merge._value2member_map_:
|
||||
|
||||
is_valid = True
|
||||
|
||||
elif self._ticket_type == 'project_task':
|
||||
|
||||
if field in self.Meta.model.TicketStatus.ProjectTask._value2member_map_:
|
||||
|
||||
is_valid = True
|
||||
|
||||
|
||||
if not is_valid:
|
||||
|
||||
if hasattr(self, 'validated_data'):
|
||||
|
||||
raise serializers.ValidationError('Incorrect Status set')
|
||||
|
||||
else:
|
||||
|
||||
self.combined_validation_error('Incorrect Status set')
|
||||
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
def validate_ticket(self):
|
||||
"""Validations common to all ticket types."""
|
||||
|
||||
is_valid = False
|
||||
|
||||
fields: list = []
|
||||
|
||||
if hasattr(self, 'validated_data'):
|
||||
|
||||
fields = self.validated_data
|
||||
|
||||
else:
|
||||
|
||||
fields = self.cleaned_data
|
||||
|
||||
validate_field_permission = False
|
||||
if self.validate_field_permission:
|
||||
|
||||
validate_field_permission = True
|
||||
|
||||
validate_field_organization: bool = False
|
||||
if self.validate_field_organization():
|
||||
|
||||
validate_field_organization = True
|
||||
|
||||
validate_field_milestone: bool = False
|
||||
if self.validate_field_milestone():
|
||||
|
||||
validate_field_milestone: bool = True
|
||||
|
||||
|
||||
validate_field_status = False
|
||||
if self.validate_field_status():
|
||||
|
||||
validate_field_status = True
|
||||
|
||||
if (
|
||||
validate_field_permission
|
||||
and validate_field_status
|
||||
and validate_field_milestone
|
||||
and validate_field_organization
|
||||
):
|
||||
is_valid = True
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
|
||||
def validate_change_ticket(self):
|
||||
|
||||
# check status
|
||||
|
||||
# check type
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def validate_incident_ticket(self):
|
||||
|
||||
# check status
|
||||
|
||||
# check type
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def validate_problem_ticket(self):
|
||||
|
||||
# check status
|
||||
|
||||
# check type
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def validate_request_ticket(self):
|
||||
|
||||
# check status
|
||||
|
||||
# check type
|
||||
|
||||
# self.combined_validation_error('Test to see what it looks like')
|
||||
pass
|
||||
|
||||
def validate_project_task_ticket(self):
|
||||
|
||||
if hasattr(self,'_project'):
|
||||
self.cleaned_data.update({
|
||||
'project': self._project
|
||||
})
|
||||
|
||||
if self.cleaned_data['project'] is None:
|
||||
|
||||
self.combined_validation_error('A project task requires a project')
|
@ -1,276 +0,0 @@
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.forms import ValidationError
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from access.mixin import OrganizationMixin
|
||||
|
||||
|
||||
class TicketCommentValidation(
|
||||
OrganizationMixin,
|
||||
):
|
||||
|
||||
|
||||
original_object = None
|
||||
|
||||
_comment_type:str = None
|
||||
"""Human readable comment type. i.e. `request` in lowercase"""
|
||||
|
||||
_has_add_permission: bool = False
|
||||
|
||||
_has_change_permission: bool = False
|
||||
|
||||
_has_delete_permission: bool = False
|
||||
|
||||
_has_import_permission: bool = False
|
||||
|
||||
_has_triage_permission: bool = False
|
||||
|
||||
_ticket_organization = None
|
||||
"""Ticket Organization as a organization object"""
|
||||
|
||||
_ticket_type: str = None
|
||||
"""Human readable type of ticket. i.e. `request` in lowercase"""
|
||||
|
||||
request = None
|
||||
|
||||
add_fields: list = [
|
||||
'body',
|
||||
'duration'
|
||||
]
|
||||
|
||||
change_fields: list = [
|
||||
'body',
|
||||
]
|
||||
|
||||
delete_fields: list = [
|
||||
'is_deleted',
|
||||
]
|
||||
|
||||
import_fields: list = [
|
||||
'organization',
|
||||
'parent',
|
||||
'ticket',
|
||||
'external_ref',
|
||||
'external_system',
|
||||
'comment_type',
|
||||
'body',
|
||||
'category',
|
||||
'created',
|
||||
'modified',
|
||||
'private',
|
||||
'duration',
|
||||
'template',
|
||||
'is_template',
|
||||
'source',
|
||||
'status',
|
||||
'responsible_user',
|
||||
'responsible_team',
|
||||
'user',
|
||||
'date_closed',
|
||||
'planned_start_date',
|
||||
'planned_finish_date',
|
||||
'real_start_date',
|
||||
'real_finish_date',
|
||||
]
|
||||
|
||||
triage_fields: list = [
|
||||
'category',
|
||||
'body',
|
||||
'private',
|
||||
'duration',
|
||||
'template',
|
||||
'is_template',
|
||||
'source',
|
||||
'status',
|
||||
'responsible_user',
|
||||
'responsible_team',
|
||||
'planned_start_date',
|
||||
'planned_finish_date',
|
||||
'real_start_date',
|
||||
'real_finish_date',
|
||||
]
|
||||
|
||||
|
||||
@property
|
||||
def fields_allowed(self) -> list(str()):
|
||||
""" Get the allowed fields for a ticket ccomment
|
||||
|
||||
Returns:
|
||||
list(str): A list of allowed fields for the user
|
||||
"""
|
||||
|
||||
if self.request is None:
|
||||
|
||||
raise ValueError('Attribute self.request must be set')
|
||||
|
||||
|
||||
fields_allowed: list = []
|
||||
|
||||
|
||||
if self._has_add_permission and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = self.add_fields
|
||||
|
||||
|
||||
if self._has_change_permission and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = self.change_fields
|
||||
|
||||
if self._has_delete_permission and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = fields_allowed + self.delete_fields
|
||||
|
||||
if self._has_import_permission and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = fields_allowed + self.import_fields
|
||||
|
||||
if self._has_triage_permission and not self.request.user.is_superuser:
|
||||
|
||||
fields_allowed = fields_allowed + self.triage_fields
|
||||
|
||||
if self.request.user.is_superuser:
|
||||
|
||||
all_fields: list = self.add_fields
|
||||
all_fields = all_fields + self.change_fields
|
||||
all_fields = all_fields + self.delete_fields
|
||||
all_fields = all_fields + self.import_fields
|
||||
all_fields = all_fields + self.triage_fields
|
||||
|
||||
fields_allowed = fields_allowed + all_fields
|
||||
|
||||
comment_fields = []
|
||||
|
||||
|
||||
if (
|
||||
self._ticket_type == 'request'
|
||||
or
|
||||
self._ticket_type == 'incident'
|
||||
or
|
||||
self._ticket_type == 'problem'
|
||||
or
|
||||
self._ticket_type == 'change'
|
||||
or
|
||||
self._ticket_type == 'project_task'
|
||||
):
|
||||
|
||||
if self._comment_type == 'task':
|
||||
|
||||
comment_fields = self.Meta.model.fields_itsm_task
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.TASK
|
||||
|
||||
elif self._comment_type == 'comment':
|
||||
|
||||
comment_fields = self.Meta.model.common_itsm_fields
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.COMMENT
|
||||
|
||||
|
||||
elif self._comment_type == 'solution':
|
||||
|
||||
comment_fields = self.Meta.model.common_itsm_fields
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.SOLUTION
|
||||
|
||||
elif self._comment_type == 'notification':
|
||||
|
||||
comment_fields = self.Meta.model.fields_itsm_notification
|
||||
|
||||
self.fields['comment_type'].initial = self.Meta.model.CommentType.NOTIFICATION
|
||||
|
||||
elif self._ticket_type == 'issue':
|
||||
|
||||
comment_fields = self.Meta.model.fields_git_issue
|
||||
|
||||
elif self._ticket_type == 'merge':
|
||||
|
||||
comment_fields = self.Meta.model.fields_git_merge
|
||||
|
||||
|
||||
for comment_field in comment_fields:
|
||||
|
||||
if comment_field not in fields_allowed:
|
||||
|
||||
comment_fields.remove(comment_field)
|
||||
|
||||
return comment_fields
|
||||
|
||||
|
||||
@property
|
||||
def ticket_comment_permissions(self):
|
||||
|
||||
if self._ticket_organization is None:
|
||||
|
||||
raise ValueError('Attribute self._ticket_organization must be set')
|
||||
|
||||
|
||||
if self.request is None:
|
||||
|
||||
raise ValueError('Attribute self.request must be set')
|
||||
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=self._ticket_organization.id,
|
||||
permissions_required = [ 'core.add_ticket_'+ self._ticket_type ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
self._has_add_permission = True
|
||||
|
||||
if (
|
||||
self.has_organization_permission(
|
||||
organization=self._ticket_organization.id,
|
||||
permissions_required = [ 'core.change_ticketcomment' ],
|
||||
) or
|
||||
self.request.user.id == self.instance.user_id
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
self._has_change_permission = True
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=self._ticket_organization.id,
|
||||
permissions_required = [ 'core.delete_ticketcomment' ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
self._has_delete_permission = True
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=self._ticket_organization.id,
|
||||
permissions_required = [ 'core.import_ticketcomment' ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
self._has_import_permission = True
|
||||
|
||||
if self.has_organization_permission(
|
||||
organization=self._ticket_organization.id,
|
||||
permissions_required = [ 'core.triage_ticket_'+ self._ticket_type ],
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
self._has_triage_permission = True
|
||||
|
||||
if (
|
||||
not self._has_triage_permission and (
|
||||
self._comment_type == 'notification' or
|
||||
self._comment_type == 'task' or
|
||||
self._comment_type == 'solution'
|
||||
)
|
||||
) and not self.request.user.is_superuser:
|
||||
|
||||
raise PermissionDenied("You dont have permission for comment types: notification, task and solution")
|
||||
|
||||
|
||||
def validate_ticket_comment(self) -> bool:
|
||||
|
||||
is_valid: bool = True
|
||||
|
||||
self.ticket_comment_permissions
|
||||
|
||||
fields_allowed = self.fields_allowed
|
||||
|
||||
for field in self.change_fields:
|
||||
|
||||
if field not in fields_allowed:
|
||||
|
||||
raise PermissionDenied(f'You tried to edit a field ({field}) that you dont have access to edit')
|
||||
|
||||
return is_valid
|
@ -1,138 +0,0 @@
|
||||
{% extends 'base.html.j2' %}
|
||||
|
||||
{% load json %}
|
||||
{% load markdown %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<script>
|
||||
|
||||
function openCity(evt, cityName) {
|
||||
// Declare all variables
|
||||
var i, tabcontent, tablinks;
|
||||
|
||||
// Get all elements with class="tabcontent" and hide them
|
||||
tabcontent = document.getElementsByClassName("tabcontent");
|
||||
for (i = 0; i < tabcontent.length; i++) {
|
||||
tabcontent[i].style.display = "none";
|
||||
}
|
||||
|
||||
// Get all elements with class="tablinks" and remove the class "active"
|
||||
tablinks = document.getElementsByClassName("tablinks");
|
||||
for (i = 0; i < tablinks.length; i++) {
|
||||
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
||||
}
|
||||
|
||||
// Show the current tab, and add an "active" class to the button that opened the tab
|
||||
document.getElementById(cityName).style.display = "block";
|
||||
evt.currentTarget.className += " active";
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="tab">
|
||||
<button onclick="window.location='{% url 'Settings:_task_results' %}';"
|
||||
style="vertical-align: middle; padding: auto; margin: 0px">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="25px" viewBox="0 -960 960 960" width="25px"
|
||||
style="vertical-align: middle; margin: 0px; padding: 0px border: none; " fill="#6a6e73">
|
||||
<path d="m313-480 155 156q11 11 11.5 27.5T468-268q-11 11-28 11t-28-11L228-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T468-692q11 11 11 28t-11 28L313-480Zm264 0 155 156q11 11 11.5 27.5T732-268q-11 11-28 11t-28-11L492-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T732-692q11 11 11 28t-11 28L577-480Z" />
|
||||
</svg> Back to Task Results</button>
|
||||
<button id="defaultOpen" class="tablinks" onclick="openCity(event, 'Details')">Details</button>
|
||||
<!-- <button class="tablinks" onclick="openCity(event, 'Installations')">Installations</button> -->
|
||||
</div>
|
||||
<style>
|
||||
|
||||
.detail-view-field {
|
||||
display:unset;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0px 20px 40px 20px;
|
||||
|
||||
}
|
||||
|
||||
.detail-view-field label {
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
width: 200px;
|
||||
margin: 10px;
|
||||
/*padding: 10px;*/
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
}
|
||||
|
||||
.detail-view-field span {
|
||||
display: inline-block;
|
||||
width: 340px;
|
||||
margin: 10px;
|
||||
/*padding: 10px;*/
|
||||
border-bottom: 1px solid #ccc;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="Details" class="tabcontent">
|
||||
|
||||
<h3>Details </h3>
|
||||
|
||||
<div style="align-items:flex-start; align-content: center; display: flexbox; width: 100%">
|
||||
|
||||
<div style="display: inline; width: 40%; margin: 30px;">
|
||||
|
||||
<div class="detail-view-field">
|
||||
<label>{{ form.task_id.label }}</label>
|
||||
<span>{{ form.task_id.value }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-view-field">
|
||||
<label>{{ form.task_name.label }}</label>
|
||||
<span>{{ form.task_name.value }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-view-field">
|
||||
<label>{{ form.status.label }}</label>
|
||||
<span>{{ form.status.value }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-view-field">
|
||||
<label>Created</label>
|
||||
<span>{{ task_result.date_created }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-view-field">
|
||||
<label>Finished</label>
|
||||
<span>{{ task_result.date_done }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="display: inline; width: 40%; margin: 30px; text-align: left;">
|
||||
<div>
|
||||
<label style="font-weight: bold; width: 100%; border-bottom: 1px solid #ccc; display: block; text-align: inherit;">{{ form.task_args.label }}</label>
|
||||
|
||||
<div style="display: inline-block; text-align: left;">{{ form.task_args.value }}</div>
|
||||
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<label style="font-weight: bold; width: 100%; border-bottom: 1px solid #ccc; display: block; text-align: inherit;">Result</label>
|
||||
|
||||
<div style="display: inline-block; text-align: left;"><pre style="text-align: left; max-width: 300px;">{{ task_result.result | json_pretty }}</pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
// Get the element with id="defaultOpen" and click on it
|
||||
document.getElementById("defaultOpen").click();
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -1,25 +0,0 @@
|
||||
{% extends 'base.html.j2' %}
|
||||
|
||||
{% block content %}
|
||||
<input type="button" value="<< Back to settings" onclick="window.location='{% url 'Settings:Settings' %}';">
|
||||
|
||||
<table style="max-width: 100%;">
|
||||
<thead>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Created</th>
|
||||
<th>Completed</th>
|
||||
</thead>
|
||||
{% for entry in task_results %}
|
||||
<tr class="clicker">
|
||||
<td><a href="{% url 'Settings:_task_result_view' pk=entry.id %}">{{ entry.task_id }}</a></td>
|
||||
<td>{{ entry.task_name }}</td>
|
||||
<td>{{ entry.status }}</td>
|
||||
<td>{{ entry.date_created }}</td>
|
||||
<td>{{ entry.date_done }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,47 +0,0 @@
|
||||
{% extends 'base.html.j2' %}
|
||||
|
||||
{% block content %}
|
||||
<input type="button" value="<< Back to settings" onclick="window.location='{% url 'Settings:Settings' %}';">
|
||||
<input type="button" value="New Category" onclick="window.location='{% url 'Settings:_ticket_category_add' %}';">
|
||||
|
||||
<table style="max-width: 100%;">
|
||||
<thead>
|
||||
<th>Name</th>
|
||||
<th>Organization</th>
|
||||
<th>created</th>
|
||||
<th>modified</th>
|
||||
<th> </th>
|
||||
</thead>
|
||||
{% if items %}
|
||||
{% for category in items %}
|
||||
<tr>
|
||||
<td><a href="{% url 'Settings:_ticket_category_view' pk=category.id %}">{{ category.name }}</a></td>
|
||||
<td>{{ category.organization }}</td>
|
||||
<td>{{ category.created }}</td>
|
||||
<td>{{ category.modified }}</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr><td colspan="5">Nothing Found</td></tr>
|
||||
{% endif%}
|
||||
</table>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="step-links">
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page=1">« first</a>
|
||||
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
|
||||
{% endif %}
|
||||
|
||||
<span class="current">
|
||||
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
|
||||
</span>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}">next</a>
|
||||
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endblock %}
|
@ -1,47 +0,0 @@
|
||||
{% extends 'base.html.j2' %}
|
||||
|
||||
{% block content %}
|
||||
<input type="button" value="<< Back to settings" onclick="window.location='{% url 'Settings:Settings' %}';">
|
||||
<input type="button" value="New Category" onclick="window.location='{% url 'Settings:_ticket_comment_category_add' %}';">
|
||||
|
||||
<table style="max-width: 100%;">
|
||||
<thead>
|
||||
<th>Name</th>
|
||||
<th>Organization</th>
|
||||
<th>created</th>
|
||||
<th>modified</th>
|
||||
<th> </th>
|
||||
</thead>
|
||||
{% if items %}
|
||||
{% for category in items %}
|
||||
<tr>
|
||||
<td><a href="{% url 'Settings:_ticket_comment_category_view' pk=category.id %}">{{ category.name }}</a></td>
|
||||
<td>{{ category.organization }}</td>
|
||||
<td>{{ category.created }}</td>
|
||||
<td>{{ category.modified }}</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr><td colspan="5">Nothing Found</td></tr>
|
||||
{% endif%}
|
||||
</table>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="step-links">
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page=1">« first</a>
|
||||
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
|
||||
{% endif %}
|
||||
|
||||
<span class="current">
|
||||
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
|
||||
</span>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}">next</a>
|
||||
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endblock %}
|
@ -1,34 +0,0 @@
|
||||
{% extends 'detail.html.j2' %}
|
||||
|
||||
{% load json %}
|
||||
{% load markdown %}
|
||||
|
||||
|
||||
{% block tabs %}
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div id="details" class="content-tab">
|
||||
|
||||
{% include 'content/section.html.j2' with tab=form.tabs.details %}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="notes" class="content-tab">
|
||||
|
||||
{% include 'content/section.html.j2' with tab=form.tabs.notes %}
|
||||
|
||||
{{ notes_form }}
|
||||
<input type="submit" name="{{notes_form.prefix}}" value="Submit" />
|
||||
<div class="comments">
|
||||
{% if notes %}
|
||||
{% for note in notes%}
|
||||
{% include 'note.html.j2' %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
@ -1,163 +0,0 @@
|
||||
{% extends 'base.html.j2' %}
|
||||
|
||||
{% block additional-stylesheet %}
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href="{% static 'ticketing.css' %}">
|
||||
{% endblock additional-stylesheet %}
|
||||
|
||||
{% load markdown %}
|
||||
|
||||
{% block article %}
|
||||
|
||||
<div id="ticket-content">
|
||||
|
||||
<div id="ticket-data">
|
||||
|
||||
<div id="ticket-description">
|
||||
<h3 class="{{ ticket_type }}-ticket">
|
||||
<span class="sub-script">opened by</span> {{ ticket.opened_by }} <span class="sub-script">on</span> {{ ticket.created }}
|
||||
{% if ticket.created|date_time_seconds != ticket.modified|date_time_seconds %}
|
||||
<span class="sub-script">Updated</span> {{ ticket.modified }}
|
||||
{% endif %}
|
||||
</h3>
|
||||
<div>
|
||||
<input style="float: right; position: relative; margin: 0px;" type="button" value="Edit" onclick="window.location='{{ edit_url }}';">
|
||||
</div>
|
||||
<div id="markdown">{{ ticket.description | markdown | safe }}</div>
|
||||
</div>
|
||||
|
||||
<div id="ticket-additional-data">
|
||||
|
||||
<div id="data-block">
|
||||
<h3>
|
||||
<div id="text">Related Tickets</div>
|
||||
<div id="icons">
|
||||
<a href="{% url '_ticket_related_add' ticket_type=ticket_type ticket_id=ticket.id %}">{% include 'icons/ticket/add.svg' %}</a>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
{% if ticket.related_tickets %}
|
||||
{% for related_ticket in ticket.related_tickets %}
|
||||
<div id="linked-tickets" class="{{ related_ticket.type }}-ticket">
|
||||
<div class="icon icon-{{ related_ticket.how_related }}">{% include related_ticket.icon_filename %}</div>
|
||||
<div id="markdown" class="ticket">
|
||||
{% if related_ticket.how_related == 'blocked_by' %}
|
||||
Blocked by
|
||||
{% elif related_ticket.how_related == 'blocks' %}
|
||||
Blocks
|
||||
{% elif related_ticket.how_related == 'related' %}
|
||||
Related to
|
||||
{% endif %}
|
||||
<span style="display: inline-block;">{{ related_ticket.markdown | markdown | safe }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div>Nothing Found</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="data-block" class="linked-item">
|
||||
<h3>
|
||||
<div id="text">Linked Items</div>
|
||||
<div id="icons">
|
||||
<a href="{% url '_ticket_linked_item_add' ticket_type=ticket_type ticket_id=ticket.id %}">{% include 'icons/ticket/add.svg' %}</a>
|
||||
</div>
|
||||
</h3>
|
||||
{% if ticket.linked_items %}
|
||||
{% for linked_item in ticket.linked_items %}
|
||||
<div id="item">{{ linked_item | markdown | safe }}</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div style="text-align:center;%">Nothing found</div>
|
||||
{% endif%}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% include 'core/ticket/comment.html.j2' %}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="ticket-meta">
|
||||
<h3 class="{{ ticket_type }}-ticket">
|
||||
{{ ticket_type }} <span style="font-size: smaller;">#{{ ticket.id }}
|
||||
{% if ticket.external_ref %}
|
||||
<span style="display: inline-block;" title="External system {{ ticket.get_external_system_display }}">(#{{ ticket.external_ref }})</span>
|
||||
{% endif %}</span>
|
||||
</h3>
|
||||
|
||||
<fieldset>
|
||||
<label>Assigned</label>
|
||||
<span class="text">
|
||||
{% if ticket.assigned_users %}
|
||||
{% for user in ticket.assigned_users.all %}
|
||||
{{ user }}
|
||||
{% endfor%}
|
||||
{% endif %}
|
||||
{% if ticket.assigned_teams %}
|
||||
{% for team in ticket.assigned_teams.all %}
|
||||
{{ team }}
|
||||
{% endfor%}
|
||||
{% endif %}
|
||||
</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>Status</label>
|
||||
<span>{% include 'core/ticket/badge_ticket_status.html.j2' with ticket_status_text=ticket.get_status_display ticket_status=ticket.get_status_display|ticket_status %}</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>Labels</label>
|
||||
<span class="text">val</span>
|
||||
</fieldset>
|
||||
{% if ticket.category %}
|
||||
<fieldset>
|
||||
<label>Category</label>
|
||||
<span class="text">
|
||||
<a href="{% url 'Settings:_ticket_category_view' pk=ticket.category.id %}">
|
||||
{{ ticket.category }}
|
||||
</a>
|
||||
</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if ticket.project %}
|
||||
<fieldset>
|
||||
<label>Project</label>
|
||||
<span class="text">
|
||||
<a href="{% url 'Project Management:_project_view' pk=ticket.project_id %}">{{ ticket.project }}</a>
|
||||
</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if ticket.milestone %}
|
||||
<fieldset>
|
||||
<label>Milestone</label>
|
||||
<span class="text">
|
||||
<a href="{% url 'Project Management:_project_milestone_view' project_id=ticket.project_id pk=ticket.milestone.id %}">{{ ticket.milestone }}</a>
|
||||
</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<label>Priority</label>
|
||||
<span class="text">U{{ ticket.get_urgency_display }} / I{{ ticket.get_impact_display }} / P{{ ticket.get_priority_display }}</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>Duration</label>
|
||||
<span class="text">{{ ticket.duration_ticket|to_duration }}</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>Milestone</label>
|
||||
<span class="text">val</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>Roadmap(s)</label>
|
||||
<span class="text">val</span>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
@ -1,6 +0,0 @@
|
||||
<span id="badge">
|
||||
<span id="icon" class="ticket-status ticket-status-{{ ticket_status }}">
|
||||
{% include 'core/ticket/icon_status.html.j2' %}
|
||||
</span>
|
||||
<span id="text">{{ ticket_status_text }}</span>
|
||||
</span>
|
@ -1,89 +0,0 @@
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
{% if ticket_type == 'change'%}
|
||||
{% translate 'ITIM:_ticket_comment_change_reply_add' as comment_reply_url %}
|
||||
{% elif ticket_type == 'incident'%}
|
||||
{% translate 'ITIM:_ticket_comment_incident_reply_add' as comment_reply_url %}
|
||||
{% elif ticket_type == 'project_task'%}
|
||||
{% translate 'Project Management:_project_task_comment_reply_add' as comment_reply_url %}
|
||||
{% elif ticket_type == 'problem'%}
|
||||
{% translate 'ITIM:_ticket_comment_problem_reply_add' as comment_reply_url %}
|
||||
{% elif ticket_type == 'request'%}
|
||||
{% translate 'Assistance:_ticket_comment_request_reply_add' as comment_reply_url %}
|
||||
{% endif %}
|
||||
|
||||
<div id="ticket-comments">
|
||||
<ul>
|
||||
|
||||
{% for comment in ticket.comments %}
|
||||
|
||||
<li {% if comment.get_comment_type_display == 'Action' %}id="{{ comment.get_comment_type_display }}"{% endif %}>
|
||||
{% include 'core/ticket/comment/comment.html.j2' %}
|
||||
|
||||
{% if comment.threads %}
|
||||
<div id="discussion" style="/*background-color: #fff;*/">
|
||||
<h4 style="display: flex; padding-left: 5px;">
|
||||
Replies
|
||||
{% include 'icons/ticket/expanded.svg' %}
|
||||
</h4>
|
||||
</div>
|
||||
<div style="padding-left: 40px; border-left: 1px solid #177fe66e; border-bottom: 1px solid #177fe66e;">
|
||||
{% if comment.threads %}
|
||||
{% for thread in comment.threads %}
|
||||
|
||||
|
||||
{% include 'core/ticket/comment/comment.html.j2' with comment=thread %}
|
||||
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
<div >
|
||||
<div style="padding: 10px; padding-top: 10px">
|
||||
|
||||
{% if ticket_type == 'project_task'%}
|
||||
<input type="button" value="Comment" onclick="window.location='{% url comment_reply_url ticket.project.id ticket_type ticket.id comment.id %}?comment_type=comment';">
|
||||
<input type="button" value="Task" onclick="window.location='{% url comment_reply_url ticket.project.id ticket_type ticket.id comment.id %}?comment_type=task';">
|
||||
{% else %}
|
||||
<input type="button" value="Comment" onclick="window.location='{% url comment_reply_url ticket_type ticket.id comment.id %}?comment_type=comment';">
|
||||
<input type="button" value="Task" onclick="window.location='{% url comment_reply_url ticket_type ticket.id comment.id %}?comment_type=task';">
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</ul>
|
||||
|
||||
<div id="comment" style="padding: 20px;">
|
||||
|
||||
{% if ticket_type == 'change'%}
|
||||
{% translate 'ITIM:_ticket_comment_change_add' as comment_url %}
|
||||
{% elif ticket_type == 'incident'%}
|
||||
{% translate 'ITIM:_ticket_comment_incident_add' as comment_url %}
|
||||
{% elif ticket_type == 'project_task'%}
|
||||
{% translate 'Project Management:_project_task_comment_add' as comment_url %}
|
||||
{% elif ticket_type == 'problem'%}
|
||||
{% translate 'ITIM:_ticket_comment_problem_add' as comment_url %}
|
||||
{% elif ticket_type == 'request'%}
|
||||
{% translate 'Assistance:_ticket_comment_request_add' as comment_url %}
|
||||
{% endif %}
|
||||
|
||||
{% if ticket_type == 'project_task'%}
|
||||
<input type="button" value="Comment" onclick="window.location='{% url comment_url ticket.project.id ticket_type ticket.id%}?comment_type=comment';">
|
||||
<input type="button" value="Task" onclick="window.location='{% url comment_url ticket.project.id ticket_type ticket.id %}?comment_type=task';">
|
||||
<input type="button" value="Notification" onclick="window.location='{% url comment_url ticket.project.id ticket_type ticket.id %}?comment_type=notification';">
|
||||
<input type="button" value="Resolve" onclick="window.location='{% url comment_url ticket.project.id ticket_type ticket.id %}?comment_type=solution';">
|
||||
{% else %}
|
||||
<input type="button" value="Comment" onclick="window.location='{% url comment_url ticket_type ticket.id%}?comment_type=comment';">
|
||||
<input type="button" value="Task" onclick="window.location='{% url comment_url ticket_type ticket.id %}?comment_type=task';">
|
||||
<input type="button" value="Notification" onclick="window.location='{% url comment_url ticket_type ticket.id %}?comment_type=notification';">
|
||||
<input type="button" value="Resolve" onclick="window.location='{% url comment_url ticket_type ticket.id %}?comment_type=solution';">
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
@ -1,132 +0,0 @@
|
||||
{% if comment %}
|
||||
|
||||
{% load markdown %}
|
||||
|
||||
{% if comment.get_comment_type_display == 'Action' %}
|
||||
|
||||
<div style="padding: 0px; margin: 0px;"><span style="display: inline-block;">{{ comment.user.username }} </span><span style="display: inline-block;">{{ comment.body | markdown | safe }}</span></div>
|
||||
|
||||
{% elif comment.get_comment_type_display == 'Comment' or comment.get_comment_type_display == 'Task' or comment.get_comment_type_display == 'Notification' or comment.get_comment_type_display == 'Solution' %}
|
||||
<div id="comment" class="comment-type-default comment-type-{{ comment.get_comment_type_display }}">
|
||||
|
||||
<h4>
|
||||
<div id="text">
|
||||
{{ comment.user }}
|
||||
<span class="sub-script">{% if comment.get_comment_type_display == 'Task' %}
|
||||
created a task
|
||||
{% elif comment.get_comment_type_display == 'Solution' %}
|
||||
solved
|
||||
{% else %}
|
||||
wrote
|
||||
{% endif %}
|
||||
on</span> {{ comment.created }}
|
||||
{% if comment.created|date_time_seconds != comment.modified|date_time_seconds %}
|
||||
<span class="sub-script">Updated</span> {{ comment.modified }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="icons">
|
||||
{%if not comment.parent_id %}
|
||||
{% if ticket_type == 'project_task'%}
|
||||
<a title="Reply with Comment" href="{% url comment_reply_url ticket.project.id ticket_type ticket.id comment.id %}?comment_type=comment">
|
||||
{% include 'icons/ticket/reply.svg' %}
|
||||
</a>
|
||||
<a title="Reply with Task" href="{% url comment_reply_url ticket.project.id ticket_type ticket.id comment.id %}?comment_type=task">
|
||||
{% include 'icons/ticket/task.svg' %}
|
||||
</a>
|
||||
<a title="Reply with Notification" href="{% url comment_reply_url ticket.project.id ticket_type ticket.id comment.id %}?comment_type=notification">
|
||||
{% include 'icons/ticket/notification.svg' %}
|
||||
</a>
|
||||
{% else %}
|
||||
<a title="Reply with Comment" href="{% url comment_reply_url ticket_type ticket.id comment.id %}?comment_type=comment">
|
||||
{% include 'icons/ticket/reply.svg' %}
|
||||
</a>
|
||||
<a title="Reply with Task" href="{% url comment_reply_url ticket_type ticket.id comment.id %}?comment_type=task">
|
||||
{% include 'icons/ticket/task.svg' %}
|
||||
</a>
|
||||
<a title="Reply with Notification" href="{% url comment_reply_url ticket_type ticket.id comment.id %}?comment_type=notification">
|
||||
{% include 'icons/ticket/notification.svg' %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<a title="Edit Comment" href="{% url 'Assistance:_ticket_comment_request_change' ticket_type ticket.id comment.id %}">
|
||||
{% include 'icons/ticket/edit.svg' %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</h4>
|
||||
|
||||
<div style="line-height:30px;">
|
||||
{% if comment.get_comment_type_display != 'Notification' %}
|
||||
<fieldset>
|
||||
<label>Source</label>
|
||||
<span>{{ comment.get_source_display }}</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if comment.get_comment_type_display == 'Task' or comment.get_comment_type_display == 'Notification' %}
|
||||
<fieldset>
|
||||
<label>Status</label>
|
||||
<span>{{ comment.get_status_display }}</span>
|
||||
</fieldset>
|
||||
{% if comment.get_comment_type_display == 'Task' %}
|
||||
<fieldset>
|
||||
<label>Responsible User</label>
|
||||
<span>{{ comment.responsible_user }}</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<label>
|
||||
{% if comment.get_comment_type_display == 'Task' %}
|
||||
Responsible Team
|
||||
{% elif comment.get_comment_type_display == 'Notification' %}
|
||||
Notify Team
|
||||
{% endif %}
|
||||
</label>
|
||||
<span>{{ comment.responsible_team }}</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<label>Category</label>
|
||||
<span>{{ comment.category }}</span>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div id="markdown" style="margin: 15px; padding: 10px; background-color: #fff;">
|
||||
{{ comment.body | markdown | safe }}
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div>
|
||||
{% if comment.get_comment_type_display == 'Task' or comment.get_comment_type_display == 'Notification' %}
|
||||
<fieldset>
|
||||
<label>Planned Start</label>
|
||||
<span>{{ comment.planned_start_date }}</span>
|
||||
</fieldset>
|
||||
{% if comment.get_comment_type_display == 'Task' %}
|
||||
<fieldset>
|
||||
<label>Planned Finish</label>
|
||||
<span>{{ comment.planned_finish_date }}</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<label>Actual Start</label>
|
||||
<span>{{ comment.real_start_date }}</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>Actual Finish</label>
|
||||
<span>{{ comment.real_finish_date }}</span>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<label>Duration</label>
|
||||
<span>{{ comment.duration|to_duration }}</span>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
@ -1,25 +0,0 @@
|
||||
{% if ticket_status == 'new' %}
|
||||
{% include 'icons/ticket/add.svg' %}
|
||||
{% elif ticket_status == 'assigned' %}
|
||||
{% include 'icons/ticket/status_assigned.svg' %}
|
||||
{% elif ticket_status == 'assigned_planning' %}
|
||||
{% include 'icons/ticket/status_assigned_planning.svg' %}
|
||||
{% elif ticket_status == 'closed' %}
|
||||
{% include 'icons/ticket/status_closed.svg' %}
|
||||
{% elif ticket_status == 'draft' %}
|
||||
{% include 'icons/ticket/add.svg' %}
|
||||
{% elif ticket_status == 'pending' %}
|
||||
{% include 'icons/ticket/status_pending.svg' %}
|
||||
{% elif ticket_status == 'solved' %}
|
||||
{% include 'icons/ticket/status_solved.svg' %}
|
||||
{% elif ticket_status == 'invalid' %}
|
||||
{% include 'icons/ticket/status_invalid.svg' %}
|
||||
{% elif ticket_status == 'approvals' %}
|
||||
{% include 'icons/ticket/status_approvals.svg' %}
|
||||
{% elif ticket_status == 'accepted' %}
|
||||
{% include 'icons/ticket/status_accepted.svg' %}
|
||||
{% elif ticket_status == 'evaluation' %}
|
||||
{% include 'icons/ticket/status_evaluation.svg' %}
|
||||
{% elif ticket_status == 'testing' %}
|
||||
{% include 'icons/ticket/status_testing.svg' %}
|
||||
{% endif %}
|
@ -1,67 +0,0 @@
|
||||
{% extends 'base.html.j2' %}
|
||||
|
||||
{% block additional-stylesheet %}
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href="{% static 'ticketing.css' %}">
|
||||
{% endblock additional-stylesheet %}
|
||||
|
||||
|
||||
{% load markdown %}
|
||||
|
||||
{% block content %}
|
||||
<input type="button" value="New Ticket" onclick="window.location='{{ new_ticket_url }}';">
|
||||
|
||||
<style>
|
||||
|
||||
#status-icon {
|
||||
margin: 0px;
|
||||
|
||||
}
|
||||
|
||||
#status-icon svg{
|
||||
width: 22px;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<table style="max-width: 100%;">
|
||||
<thead>
|
||||
<th> </th>
|
||||
<th>ID</th>
|
||||
<th>Title</th>
|
||||
<th>Status</th>
|
||||
<th>Opened By</th>
|
||||
<th>organization</th>
|
||||
<th>Created</th>
|
||||
</thead>
|
||||
{% for ticket in tickets %}
|
||||
<tr class="clicker">
|
||||
<td id="status-icon">
|
||||
|
||||
</td>
|
||||
<td>{{ ticket.id }}</td>
|
||||
<td>
|
||||
{% if ticket_type == 'change' %}
|
||||
<a href="{% url 'ITIM:_ticket_change_view' ticket_type='change' pk=ticket.id %}">
|
||||
{% elif ticket_type == 'incident' %}
|
||||
<a href="{% url 'ITIM:_ticket_incident_view' ticket_type='incident' pk=ticket.id %}">
|
||||
{% elif ticket_type == 'problem' %}
|
||||
<a href="{% url 'ITIM:_ticket_problem_view' ticket_type='problem' pk=ticket.id %}">
|
||||
{% elif ticket_type == 'request' %}
|
||||
<a href="{% url 'Assistance:_ticket_request_view' ticket_type='request' pk=ticket.id %}">
|
||||
{% else %}
|
||||
<a href=""></a>
|
||||
{% endif %}
|
||||
{{ ticket.title }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{% include 'core/ticket/badge_ticket_status.html.j2' with ticket_status_text=ticket.get_status_display ticket_status=ticket.get_status_display|ticket_status %}</td>
|
||||
<td>{{ ticket.opened_by }}</td>
|
||||
<td>{{ ticket.organization.name }}</td>
|
||||
<td>{{ ticket.created }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -1,17 +0,0 @@
|
||||
|
||||
<span id="rendered-ticket-link">
|
||||
<span id="icon" class="ticket-status ticket-status-{{ ticket_status }}">{% include 'core/ticket/icon_status.html.j2' %}</span>
|
||||
<span id="text">
|
||||
<a href=" {% if ticket_type == 'change' %}
|
||||
{% url 'ITIM:_ticket_change_view' ticket_type='change' pk=id %}
|
||||
{% elif ticket_type == 'incident' %}
|
||||
{% url 'ITIM:_ticket_incident_view' ticket_type='incident' pk=id %}
|
||||
{% elif ticket_type == 'problem' %}
|
||||
{% url 'ITIM:_ticket_problem_view' ticket_type='problem' pk=id %}
|
||||
{% elif ticket_type == 'request' %}
|
||||
{% url 'Assistance:_ticket_request_view' ticket_type='request' pk=id %}
|
||||
{% elif ticket_type == 'project task' %}
|
||||
{% url 'Project Management:_project_task_view' project_id=project_id ticket_type='project_task' pk=id %}
|
||||
{% endif %}"><span style="color: #777;">#{{ id }}</span> {{ name }}, <span style="color: #777;">{{ ticket_type }}</span></a>
|
||||
</span>
|
||||
</span>
|
@ -1,8 +0,0 @@
|
||||
<span id="ticket-icon">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" class="{{ ticket_type }}-ticket">
|
||||
|
||||
<path d="M319.33-246.67h321.34v-66.66H319.33v66.66Zm0-166.66h321.34V-480H319.33v66.67ZM226.67-80q-27 0-46.84-19.83Q160-119.67 160-146.67v-666.66q0-27 19.83-46.84Q199.67-880 226.67-880H574l226 226v507.33q0 27-19.83 46.84Q760.33-80 733.33-80H226.67Zm314-542.67v-190.66h-314v666.66h506.66v-476H540.67Zm-314-190.66v190.66-190.66 666.66-666.66Z"/>
|
||||
</svg>
|
||||
|
||||
</span>
|
@ -1,12 +0,0 @@
|
||||
{% extends 'detail.html.j2' %}
|
||||
|
||||
|
||||
{% block tabs %}
|
||||
|
||||
<div id="details" class="content-tab">
|
||||
|
||||
{% include 'content/section.html.j2' with tab=form.tabs.details %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -1,12 +0,0 @@
|
||||
{% extends 'detail.html.j2' %}
|
||||
|
||||
|
||||
{% block tabs %}
|
||||
|
||||
<div id="details" class="content-tab">
|
||||
|
||||
{% include 'content/section.html.j2' with tab=form.tabs.details %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
Before Width: | Height: | Size: 425 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M200-200h57l391-391-57-57-391 391v57Zm-80 80v-170l528-527q12-11 26.5-17t30.5-6q16 0 31 6t26 18l55 56q12 11 17.5 26t5.5 30q0 16-5.5 30.5T817-647L290-120H120Zm640-584-56-56 56 56Zm-141 85-28-29 57 57-29-28Z"/></svg>
|
Before Width: | Height: | Size: 287 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M480-345 240-585l56-56 184 183 184-183 56 56-240 240Z"/></svg>
|
Before Width: | Height: | Size: 136 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M448-201.33h66.67V-391l76 76 46.66-47L480-516.67l-156 156L371-314l77-77v189.67ZM226.67-80q-27 0-46.84-19.83Q160-119.67 160-146.67v-666.66q0-27 19.83-46.84Q199.67-880 226.67-880H574l226 226v507.33q0 27-19.83 46.84Q760.33-80 733.33-80H226.67Zm314-542.67v-190.66h-314v666.66h506.66v-476H540.67Zm-314-190.66v190.66-190.66 666.66-666.66Z"/></svg>
|
Before Width: | Height: | Size: 415 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z"/></svg>
|
Before Width: | Height: | Size: 199 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M423.28-291.22 708.87-576.8l-62.46-62.7-223.13 223.13L312.15-527.5l-62.45 62.7 173.58 173.58ZM480-71.87q-84.91 0-159.34-32.12-74.44-32.12-129.5-87.17-55.05-55.06-87.17-129.5Q71.87-395.09 71.87-480t32.12-159.34q32.12-74.44 87.17-129.5 55.06-55.05 129.5-87.17 74.43-32.12 159.34-32.12t159.34 32.12q74.44 32.12 129.5 87.17 55.05 55.06 87.17 129.5 32.12 74.43 32.12 159.34t-32.12 159.34q-32.12 74.44-87.17 129.5-55.06 55.05-129.5 87.17Q564.91-71.87 480-71.87Zm0-91q133.04 0 225.09-92.04 92.04-92.05 92.04-225.09 0-133.04-92.04-225.09-92.05-92.04-225.09-92.04-133.04 0-225.09 92.04-92.04 92.05-92.04 225.09 0 133.04 92.04 225.09 92.05 92.04 225.09 92.04ZM480-480Z"/></svg>
|
Before Width: | Height: | Size: 741 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M477.28-240q21.96 0 37.3-15.34 15.33-15.33 15.33-37.32 0-21.99-15.33-37.18-15.34-15.18-37.3-15.18-21.95 0-37.29 15.18-15.34 15.19-15.34 37.18 0 21.99 15.34 37.32Q455.33-240 477.28-240Zm-38.63-154h78.78q0-32.04 7.62-51.28 7.62-19.24 41.43-51.29 25.28-25.04 40.16-48.91 14.88-23.87 14.88-57.39 0-56.89-40.52-87.25t-96.52-30.36q-57.96 0-94.65 31.2-36.7 31.19-51.18 74.63l71.26 27.67q5.48-18.48 22.38-39.24 16.91-20.76 50.99-20.76 29.13 0 43.94 16.31 14.8 16.3 14.8 35.87 0 18.8-11.64 35.94-11.64 17.14-27.97 30.71-43.04 38.52-53.4 59.36-10.36 20.83-10.36 74.79ZM480-71.87q-84.91 0-159.34-32.12-74.44-32.12-129.5-87.17-55.05-55.06-87.17-129.5Q71.87-395.09 71.87-480t32.12-159.34q32.12-74.44 87.17-129.5 55.06-55.05 129.5-87.17 74.43-32.12 159.34-32.12t159.34 32.12q74.44 32.12 129.5 87.17 55.05 55.06 87.17 129.5 32.12 74.43 32.12 159.34t-32.12 159.34q-32.12 74.44-87.17 129.5-55.06 55.05-129.5 87.17Q564.91-71.87 480-71.87Zm0-91q133.04 0 225.09-92.04 92.04-92.05 92.04-225.09 0-133.04-92.04-225.09-92.05-92.04-225.09-92.04-133.04 0-225.09 92.04-92.04 92.05-92.04 225.09 0 133.04 92.04 225.09 92.05 92.04 225.09 92.04ZM480-480Z"/></svg>
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
Before Width: | Height: | Size: 397 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M325.07-325.07h69.86v-309.86h-69.86v309.86Zm160-4.65L710.87-480l-225.8-150.28v300.56ZM480.02-73.3q-83.95 0-158.14-31.96-74.19-31.96-129.43-87.19-55.23-55.24-87.19-129.41Q73.3-396.03 73.3-479.98q0-84.61 31.96-158.81 31.96-74.19 87.17-129.1t129.39-86.94q74.18-32.03 158.14-32.03 84.63 0 158.85 32.02 74.21 32.02 129.1 86.91 54.9 54.88 86.92 129.08 32.03 74.2 32.03 158.85 0 83.97-32.03 158.16t-86.94 129.41q-54.91 55.21-129.08 87.17Q564.64-73.3 480.02-73.3Zm-.02-75.76q138.38 0 234.66-96.51 96.28-96.52 96.28-234.43 0-138.38-96.28-234.66t-234.74-96.28q-137.79 0-234.33 96.28-96.53 96.28-96.53 234.74 0 137.79 96.51 234.33 96.52 96.53 234.43 96.53ZM480-480Z"/></svg>
|
Before Width: | Height: | Size: 737 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M318.09-318.09h323.82v-323.82H318.09v323.82ZM480-71.87q-84.91 0-159.34-32.12-74.44-32.12-129.5-87.17-55.05-55.06-87.17-129.5Q71.87-395.09 71.87-480t32.12-159.34q32.12-74.44 87.17-129.5 55.06-55.05 129.5-87.17 74.43-32.12 159.34-32.12t159.34 32.12q74.44 32.12 129.5 87.17 55.05 55.06 87.17 129.5 32.12 74.43 32.12 159.34t-32.12 159.34q-32.12 74.44-87.17 129.5-55.06 55.05-129.5 87.17Q564.91-71.87 480-71.87Zm0-91q133.04 0 225.09-92.04 92.04-92.05 92.04-225.09 0-133.04-92.04-225.09-92.05-92.04-225.09-92.04-133.04 0-225.09 92.04-92.04 92.05-92.04 225.09 0 133.04 92.04 225.09 92.05 92.04 225.09 92.04ZM480-480Z"/></svg>
|
Before Width: | Height: | Size: 692 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M480-280q83 0 141.5-58.5T680-480h-60q0 58-41 99t-99 41q-58 0-99-41t-41-99q0-58 41-99t99-41h2.28L434-570l42 43 120-120-120-120-43 43 44 44q-82 2-139.5 60T280-480q0 83 58.5 141.5T480-280Zm0 208.13q-84.91 0-159.34-32.12-74.44-32.12-129.5-87.17-55.05-55.06-87.17-129.5Q71.87-395.09 71.87-480t32.12-159.34q32.12-74.44 87.17-129.5 55.06-55.05 129.5-87.17 74.43-32.12 159.34-32.12t159.34 32.12q74.44 32.12 129.5 87.17 55.05 55.06 87.17 129.5 32.12 74.43 32.12 159.34t-32.12 159.34q-32.12 74.44-87.17 129.5-55.06 55.05-129.5 87.17Q564.91-71.87 480-71.87Zm0-91q133.04 0 225.09-92.04 92.04-92.05 92.04-225.09 0-133.04-92.04-225.09-92.05-92.04-225.09-92.04-133.04 0-225.09 92.04-92.04 92.05-92.04 225.09 0 133.04 92.04 225.09 92.05 92.04 225.09 92.04ZM480-480Z"/></svg>
|
Before Width: | Height: | Size: 832 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M479.95-271.87q19.92 0 33.45-13.48 13.53-13.48 13.53-33.4 0-19.92-13.47-33.58-13.48-13.65-33.41-13.65-19.92 0-33.45 13.65-13.53 13.66-13.53 33.58 0 19.92 13.47 33.4 13.48 13.48 33.41 13.48ZM434.5-439.52h91v-245.5h-91v245.5ZM480-71.87q-84.91 0-159.34-32.12-74.44-32.12-129.5-87.17-55.05-55.06-87.17-129.5Q71.87-395.09 71.87-480t32.12-159.34q32.12-74.44 87.17-129.5 55.06-55.05 129.5-87.17 74.43-32.12 159.34-32.12t159.34 32.12q74.44 32.12 129.5 87.17 55.05 55.06 87.17 129.5 32.12 74.43 32.12 159.34t-32.12 159.34q-32.12 74.44-87.17 129.5-55.06 55.05-129.5 87.17Q564.91-71.87 480-71.87Zm0-91q133.04 0 225.09-92.04 92.04-92.05 92.04-225.09 0-133.04-92.04-225.09-92.05-92.04-225.09-92.04-133.04 0-225.09 92.04-92.04 92.05-92.04 225.09 0 133.04 92.04 225.09 92.05 92.04 225.09 92.04ZM480-480Z"/></svg>
|
Before Width: | Height: | Size: 871 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M360-320h80v-320h-80v320Zm160 0h80v-320h-80v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
Before Width: | Height: | Size: 416 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m424-296 282-282-56-56-226 226-114-114-56 56 170 170Zm56 216q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
Before Width: | Height: | Size: 421 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M480-280q83 0 141.5-58.5T680-480q0-83-58.5-141.5T480-680q-83 0-141.5 58.5T280-480q0 83 58.5 141.5T480-280Zm0 208.13q-84.91 0-159.34-32.12-74.44-32.12-129.5-87.17-55.05-55.06-87.17-129.5Q71.87-395.09 71.87-480t32.12-159.34q32.12-74.44 87.17-129.5 55.06-55.05 129.5-87.17 74.43-32.12 159.34-32.12t159.34 32.12q74.44 32.12 129.5 87.17 55.05 55.06 87.17 129.5 32.12 74.43 32.12 159.34t-32.12 159.34q-32.12 74.44-87.17 129.5-55.06 55.05-129.5 87.17Q564.91-71.87 480-71.87Zm0-91q133.04 0 225.09-92.04 92.04-92.05 92.04-225.09 0-133.04-92.04-225.09-92.05-92.04-225.09-92.04-133.04 0-225.09 92.04-92.04 92.05-92.04 225.09 0 133.04 92.04 225.09 92.05 92.04 225.09 92.04ZM480-480Z"/></svg>
|
Before Width: | Height: | Size: 753 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m435.33-250 228-228L618-523.33l-183 183L338.33-437l-45 45 142 142ZM226.67-80q-27 0-46.84-19.83Q160-119.67 160-146.67v-666.66q0-27 19.83-46.84Q199.67-880 226.67-880H574l226 226v507.33q0 27-19.83 46.84Q760.33-80 733.33-80H226.67Zm314-542.67v-190.66h-314v666.66h506.66v-476H540.67Zm-314-190.66v190.66-190.66 666.66-666.66Z"/></svg>
|
Before Width: | Height: | Size: 402 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M319.33-246.67h321.34v-66.66H319.33v66.66Zm0-166.66h321.34V-480H319.33v66.67ZM226.67-80q-27 0-46.84-19.83Q160-119.67 160-146.67v-666.66q0-27 19.83-46.84Q199.67-880 226.67-880H574l226 226v507.33q0 27-19.83 46.84Q760.33-80 733.33-80H226.67Zm314-542.67v-190.66h-314v666.66h506.66v-476H540.67Zm-314-190.66v190.66-190.66 666.66-666.66Z"/></svg>
|
Before Width: | Height: | Size: 413 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
Before Width: | Height: | Size: 394 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M360-320h80v-320h-80v320Zm160 0h80v-320h-80v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
Before Width: | Height: | Size: 416 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M240-400h80q0-59 43-99.5T466-540q36 0 67 16.5t51 43.5h-64v80h200v-200h-80v62q-32-38-76.5-60T466-620q-95 0-160.5 64T240-400ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
Before Width: | Height: | Size: 491 B |
@ -1,35 +0,0 @@
|
||||
{% load markdown %}
|
||||
<div class="comment">
|
||||
|
||||
<div class="comment-header">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 -960 960 960" width="16px">
|
||||
<path
|
||||
d="M480-400q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240ZM200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Z" />
|
||||
</svg>
|
||||
<span>{{ note.created }}</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 -960 960 960" width="16px" style="">
|
||||
<path
|
||||
d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-160v-112q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v112H160Z" />
|
||||
</svg>
|
||||
<span style="">{{ note.usercreated }}</span>
|
||||
<span style="display: inline; margin-right: auto"> </span>
|
||||
</div>
|
||||
|
||||
<div class="comment-body">{{ note.note | markdown | safe }}</div>
|
||||
|
||||
<div class="comment-footer">
|
||||
<span>edited by: </span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 -960 960 960" width="16px">
|
||||
<path
|
||||
d="M480-400q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240ZM200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Z" />
|
||||
</svg>
|
||||
<span>date </span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 -960 960 960" width="16px" style="">
|
||||
<path
|
||||
d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-160v-112q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v112H160Z" />
|
||||
</svg>
|
||||
<span>username</span>
|
||||
<span style="display: inline; margin-right: auto"> </span>
|
||||
</div>
|
||||
|
||||
</div>
|
@ -1,193 +0,0 @@
|
||||
import django
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import TestCase, Client
|
||||
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from centurion.tests.abstract.model_permissions import ModelPermissions
|
||||
|
||||
from core.models.manufacturer import Manufacturer
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class ManufacturerPermissions(TestCase, ModelPermissions):
|
||||
|
||||
model = Manufacturer
|
||||
|
||||
app_namespace = 'Settings'
|
||||
|
||||
url_name_view = '_manufacturer_view'
|
||||
|
||||
url_name_add = '_manufacturer_add'
|
||||
|
||||
url_name_change = '_manufacturer_change'
|
||||
|
||||
url_name_delete = '_manufacturer_delete'
|
||||
|
||||
url_delete_response = reverse('Settings:_manufacturers')
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
. create an organization that is different to item
|
||||
2. Create a manufacturer
|
||||
3. create teams with each permission: view, add, change, delete
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization=organization,
|
||||
name = 'manufacturerone'
|
||||
)
|
||||
|
||||
|
||||
self.url_view_kwargs = {'pk': self.item.id}
|
||||
|
||||
# self.url_add_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.add_data = {'manufacturer': 'manufacturer', 'organization': self.organization.id}
|
||||
|
||||
self.url_change_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.change_data = {'manufacturer': 'manufacturer', 'organization': self.organization.id}
|
||||
|
||||
self.url_delete_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.delete_data = {'manufacturer': 'manufacturer', 'organization': self.organization.id}
|
||||
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
|
||||
|
||||
add_permissions = Permission.objects.get(
|
||||
codename = 'add_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
add_team = Team.objects.create(
|
||||
team_name = 'add_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
add_team.permissions.set([add_permissions])
|
||||
|
||||
|
||||
|
||||
change_permissions = Permission.objects.get(
|
||||
codename = 'change_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
change_team = Team.objects.create(
|
||||
team_name = 'change_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
change_team.permissions.set([change_permissions])
|
||||
|
||||
|
||||
|
||||
delete_permissions = Permission.objects.get(
|
||||
codename = 'delete_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
delete_team = Team.objects.create(
|
||||
team_name = 'delete_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
delete_team.permissions.set([delete_permissions])
|
||||
|
||||
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
self.add_user = User.objects.create_user(username="test_user_add", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = add_team,
|
||||
user = self.add_user
|
||||
)
|
||||
|
||||
self.change_user = User.objects.create_user(username="test_user_change", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = change_team,
|
||||
user = self.change_user
|
||||
)
|
||||
|
||||
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = delete_team,
|
||||
user = self.delete_user
|
||||
)
|
||||
|
||||
|
||||
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
|
||||
|
||||
|
||||
different_organization_team = Team.objects.create(
|
||||
team_name = 'different_organization_team',
|
||||
organization = different_organization,
|
||||
)
|
||||
|
||||
different_organization_team.permissions.set([
|
||||
view_permissions,
|
||||
add_permissions,
|
||||
change_permissions,
|
||||
delete_permissions,
|
||||
])
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = different_organization_team,
|
||||
user = self.different_organization_user
|
||||
)
|
@ -1,29 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import PrimaryModel
|
||||
|
||||
|
||||
|
||||
class ManufacturerViews(
|
||||
TestCase,
|
||||
PrimaryModel
|
||||
):
|
||||
|
||||
add_module = 'settings.views.manufacturer'
|
||||
add_view = 'Add'
|
||||
|
||||
change_module = add_module
|
||||
change_view = 'View'
|
||||
|
||||
delete_module = add_module
|
||||
delete_view = 'Delete'
|
||||
|
||||
display_module = add_module
|
||||
display_view = 'View'
|
||||
|
||||
index_module = add_module
|
||||
index_view = 'Index'
|
@ -1,110 +0,0 @@
|
||||
import django
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import TestCase
|
||||
|
||||
from celery import states
|
||||
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from centurion.tests.abstract.model_permissions import ModelPermissionsView
|
||||
|
||||
from django_celery_results.models import TaskResult
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class TaskResultPermissions(TestCase, ModelPermissionsView):
|
||||
|
||||
|
||||
model = TaskResult
|
||||
|
||||
app_label = 'django_celery_results'
|
||||
|
||||
app_namespace = 'Settings'
|
||||
|
||||
url_name_view = '_task_result_view'
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
. create an organization that is different to item
|
||||
2. Create a device
|
||||
3. create teams with each permission: view, add, change, delete
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
task_id='organization',
|
||||
periodic_task_name='',
|
||||
task_name = 'deviceone',
|
||||
status=states.SUCCESS,
|
||||
content_type='application/json',
|
||||
content_encoding='utf-8',
|
||||
)
|
||||
|
||||
|
||||
self.url_view_kwargs = {'pk': self.item.id}
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
|
||||
|
||||
|
||||
different_organization_team = Team.objects.create(
|
||||
team_name = 'different_organization_team',
|
||||
organization = different_organization,
|
||||
)
|
||||
|
||||
different_organization_team.permissions.set([
|
||||
view_permissions,
|
||||
])
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = different_organization_team,
|
||||
user = self.different_organization_user
|
||||
)
|
||||
|
||||
|
||||
def test_model_view_different_organizaiton_denied(self): # Test is N/A
|
||||
pass
|
@ -1,30 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import ModelDisplay, ModelIndex
|
||||
|
||||
|
||||
|
||||
class TaskResultsViews(
|
||||
TestCase,
|
||||
ModelDisplay,
|
||||
ModelIndex
|
||||
):
|
||||
|
||||
# add_module = 'core.views.celery_log'
|
||||
# add_view = 'GroupAdd'
|
||||
|
||||
# change_module = add_module
|
||||
# change_view = 'GroupView'
|
||||
|
||||
# delete_module = add_module
|
||||
# delete_view = 'GroupDelete'
|
||||
|
||||
display_module = 'core.views.celery_log'
|
||||
display_view = 'View'
|
||||
|
||||
index_module = display_module
|
||||
index_view = 'Index'
|
@ -1,193 +0,0 @@
|
||||
import django
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import TestCase, Client
|
||||
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from centurion.tests.abstract.model_permissions import ModelPermissions
|
||||
|
||||
from core.models.ticket.ticket_category import TicketCategory
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class TicketCategoryPermissions(TestCase, ModelPermissions):
|
||||
|
||||
model = TicketCategory
|
||||
|
||||
app_namespace = 'Settings'
|
||||
|
||||
url_name_view = '_ticket_category_view'
|
||||
|
||||
url_name_add = '_ticket_category_add'
|
||||
|
||||
url_name_change = '_ticket_category_change'
|
||||
|
||||
url_name_delete = '_ticket_category_delete'
|
||||
|
||||
url_delete_response = reverse('Settings:_ticket_categories')
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
. create an organization that is different to item
|
||||
2. Create a category
|
||||
3. create teams with each permission: view, add, change, delete
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization=organization,
|
||||
name = 'manufacturerone'
|
||||
)
|
||||
|
||||
|
||||
self.url_view_kwargs = {'pk': self.item.id}
|
||||
|
||||
# self.url_add_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.add_data = {'name': 'manufacturer', 'organization': self.organization.id}
|
||||
|
||||
self.url_change_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.change_data = {'name': 'manufacturer', 'organization': self.organization.id}
|
||||
|
||||
self.url_delete_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.delete_data = {'name': 'manufacturer'}
|
||||
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
|
||||
|
||||
add_permissions = Permission.objects.get(
|
||||
codename = 'add_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
add_team = Team.objects.create(
|
||||
team_name = 'add_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
add_team.permissions.set([add_permissions])
|
||||
|
||||
|
||||
|
||||
change_permissions = Permission.objects.get(
|
||||
codename = 'change_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
change_team = Team.objects.create(
|
||||
team_name = 'change_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
change_team.permissions.set([change_permissions])
|
||||
|
||||
|
||||
|
||||
delete_permissions = Permission.objects.get(
|
||||
codename = 'delete_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
delete_team = Team.objects.create(
|
||||
team_name = 'delete_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
delete_team.permissions.set([delete_permissions])
|
||||
|
||||
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
self.add_user = User.objects.create_user(username="test_user_add", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = add_team,
|
||||
user = self.add_user
|
||||
)
|
||||
|
||||
self.change_user = User.objects.create_user(username="test_user_change", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = change_team,
|
||||
user = self.change_user
|
||||
)
|
||||
|
||||
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = delete_team,
|
||||
user = self.delete_user
|
||||
)
|
||||
|
||||
|
||||
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
|
||||
|
||||
|
||||
different_organization_team = Team.objects.create(
|
||||
team_name = 'different_organization_team',
|
||||
organization = different_organization,
|
||||
)
|
||||
|
||||
different_organization_team.permissions.set([
|
||||
view_permissions,
|
||||
add_permissions,
|
||||
change_permissions,
|
||||
delete_permissions,
|
||||
])
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = different_organization_team,
|
||||
user = self.different_organization_user
|
||||
)
|
@ -1,33 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import PrimaryModel, ModelAdd, ModelChange, ModelDelete
|
||||
|
||||
|
||||
|
||||
# class TicketCommentViews(
|
||||
# TestCase,
|
||||
# PrimaryModel
|
||||
# ):
|
||||
class TicketCategoryViews(
|
||||
TestCase,
|
||||
PrimaryModel
|
||||
):
|
||||
|
||||
add_module = 'core.views.ticket_categories'
|
||||
add_view = 'Add'
|
||||
|
||||
change_module = add_module
|
||||
change_view = 'Change'
|
||||
|
||||
delete_module = add_module
|
||||
delete_view = 'Delete'
|
||||
|
||||
display_module = add_module
|
||||
display_view = 'View'
|
||||
|
||||
index_module = add_module
|
||||
index_view = 'Index'
|
@ -1,25 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import ModelDisplay, ModelIndex
|
||||
|
||||
from core.models.ticket.ticket_comment import TicketComment
|
||||
|
||||
|
||||
|
||||
class TicketCommentCommon(
|
||||
TestCase
|
||||
):
|
||||
|
||||
model = TicketComment
|
||||
|
||||
|
||||
def test_ticket_field_type_opened_by(self):
|
||||
"""Replies to comments only to occur on primary comment
|
||||
|
||||
If a comment has a 'parent_id' set, ensure the comment can't be replied to
|
||||
"""
|
||||
pass
|
@ -1,339 +0,0 @@
|
||||
import django
|
||||
import re
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import TestCase, Client
|
||||
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from centurion.tests.abstract.model_permissions import ModelPermissions, ModelPermissionsAdd, ModelPermissionsChange
|
||||
|
||||
from project_management.models.projects import Project
|
||||
|
||||
from core.models.ticket.ticket import Ticket, RelatedTickets
|
||||
from core.models.ticket.ticket_comment import TicketComment
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class TicketCommentPermissions(
|
||||
# ModelPermissions,
|
||||
ModelPermissionsAdd,
|
||||
ModelPermissionsChange,
|
||||
):
|
||||
|
||||
ticket_type:str = None
|
||||
|
||||
ticket_type_enum: int = None
|
||||
|
||||
model = TicketComment
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
. create an organization that is different to item
|
||||
2. Create a manufacturer
|
||||
3. create teams with each permission: view, add, change, delete
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
|
||||
add_permissions = Permission.objects.get(
|
||||
codename = 'add_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
add_ticket_permissions = Permission.objects.get(
|
||||
codename = 'add_' + Ticket._meta.model_name + '_' + self.ticket_type,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = Ticket._meta.app_label,
|
||||
model = Ticket._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
add_team = Team.objects.create(
|
||||
team_name = 'add_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
add_team.permissions.set([add_ticket_permissions, add_permissions])
|
||||
|
||||
|
||||
self.add_user = User.objects.create_user(username="test_user_add", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = add_team,
|
||||
user = self.add_user
|
||||
)
|
||||
|
||||
|
||||
self.ticket = Ticket.objects.create(
|
||||
organization=organization,
|
||||
title = 'A second ' + self.ticket_type + ' ticket',
|
||||
description = 'the ticket body of item two',
|
||||
ticket_type = int(Ticket.TicketType.REQUEST.value),
|
||||
opened_by = self.add_user,
|
||||
status = int(Ticket.TicketStatus.All.NEW.value)
|
||||
)
|
||||
|
||||
self.item_add_user = self.model.objects.create(
|
||||
organization=organization,
|
||||
body = 'A ' + self.ticket_type + ' ticket comment',
|
||||
ticket = self.ticket,
|
||||
comment_type = int(TicketComment.CommentType.COMMENT),
|
||||
user = self.add_user,
|
||||
# status = int(Ticket.TicketStatus.All.NEW.value)
|
||||
)
|
||||
|
||||
self.project = Project.objects.create(
|
||||
name = 'ticket permissions project name',
|
||||
organization = organization
|
||||
)
|
||||
|
||||
|
||||
self.url_add_kwargs = {'ticket_type': self.ticket_type, 'ticket_id': self.ticket.id}
|
||||
|
||||
self.add_data = {
|
||||
'body': 'an add ticket',
|
||||
'comment_type': int(TicketComment.CommentType.COMMENT.value),
|
||||
'ticket': self.ticket.id,
|
||||
'organization': self.organization.id,
|
||||
'user': self.add_user.id,
|
||||
}
|
||||
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
|
||||
change_permissions = Permission.objects.get(
|
||||
codename = 'change_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
change_team = Team.objects.create(
|
||||
team_name = 'change_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
change_team.permissions.set([change_permissions])
|
||||
|
||||
self.change_team = change_team
|
||||
|
||||
|
||||
|
||||
delete_permissions = Permission.objects.get(
|
||||
codename = 'delete_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
delete_team = Team.objects.create(
|
||||
team_name = 'delete_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
delete_team.permissions.set([delete_permissions])
|
||||
|
||||
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
self.change_user = User.objects.create_user(username="test_user_change", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = change_team,
|
||||
user = self.change_user
|
||||
)
|
||||
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization=organization,
|
||||
body = 'A ' + self.ticket_type + ' ticket comment',
|
||||
ticket = self.ticket,
|
||||
comment_type = int(TicketComment.CommentType.COMMENT),
|
||||
user = self.change_user,
|
||||
# status = int(Ticket.TicketStatus.All.NEW.value)
|
||||
)
|
||||
|
||||
|
||||
self.url_view_kwargs = {'ticket_type': self.ticket_type, 'pk': self.item.id}
|
||||
|
||||
self.url_change_kwargs = {'ticket_type': self.ticket_type, 'ticket_id': self.ticket.id, 'pk': self.item.id}
|
||||
|
||||
self.change_data = {'body': 'a change to ticket commennt'}
|
||||
|
||||
self.url_delete_kwargs = {'ticket_type': self.ticket_type, 'ticket_id': self.ticket.id, 'pk': self.item.id}
|
||||
|
||||
self.delete_data = {'body': 'a delete to ticket'}
|
||||
|
||||
|
||||
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = delete_team,
|
||||
user = self.delete_user
|
||||
)
|
||||
|
||||
|
||||
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
|
||||
|
||||
|
||||
different_organization_team = Team.objects.create(
|
||||
team_name = 'different_organization_team',
|
||||
organization = different_organization,
|
||||
)
|
||||
|
||||
different_organization_team.permissions.set([
|
||||
view_permissions,
|
||||
add_permissions,
|
||||
change_permissions,
|
||||
delete_permissions,
|
||||
])
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = different_organization_team,
|
||||
user = self.different_organization_user
|
||||
)
|
||||
|
||||
|
||||
def test_model_change_own_comment_has_permission(self):
|
||||
""" Check correct permission for change
|
||||
|
||||
Make change with user who has add permission on own comment
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
|
||||
kwargs = self.url_change_kwargs.copy()
|
||||
|
||||
kwargs['pk'] = self.item_add_user.id
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name_change, kwargs=kwargs)
|
||||
|
||||
|
||||
client.force_login(self.add_user)
|
||||
response = client.post(url, data=self.change_data)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
|
||||
class ChangeTicketCommentPermissions(TicketCommentPermissions, TestCase):
|
||||
|
||||
ticket_type = 'change'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.CHANGE.value)
|
||||
|
||||
app_namespace = 'ITIM'
|
||||
|
||||
url_name_view = '_ticket_comment_change_view'
|
||||
|
||||
url_name_add = '_ticket_comment_change_add'
|
||||
|
||||
url_name_change = '_ticket_comment_change_change'
|
||||
|
||||
url_name_delete = '_ticket_comment_change_delete'
|
||||
|
||||
url_delete_response = reverse('ITIM:Changes')
|
||||
|
||||
|
||||
|
||||
class IncidentTicketCommentPermissions(TicketCommentPermissions, TestCase):
|
||||
|
||||
ticket_type = 'incident'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.INCIDENT.value)
|
||||
|
||||
app_namespace = 'ITIM'
|
||||
|
||||
url_name_view = '_ticket_comment_incident_view'
|
||||
|
||||
url_name_add = '_ticket_comment_incident_add'
|
||||
|
||||
url_name_change = '_ticket_comment_incident_change'
|
||||
|
||||
url_name_delete = '_ticket_comment_incident_delete'
|
||||
|
||||
url_delete_response = reverse('ITIM:Incidents')
|
||||
|
||||
|
||||
|
||||
class ProblemTicketCommentPermissions(TicketCommentPermissions, TestCase):
|
||||
|
||||
ticket_type = 'problem'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.PROBLEM.value)
|
||||
|
||||
app_namespace = 'ITIM'
|
||||
|
||||
url_name_view = '_ticket_comment_problem_view'
|
||||
|
||||
url_name_add = '_ticket_comment_problem_add'
|
||||
|
||||
url_name_change = '_ticket_comment_problem_change'
|
||||
|
||||
url_name_delete = '_ticket_comment_problem_delete'
|
||||
|
||||
url_delete_response = reverse('ITIM:Problems')
|
||||
|
||||
|
||||
|
||||
class RequestTicketCommentPermissions(TicketCommentPermissions, TestCase):
|
||||
|
||||
ticket_type = 'request'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.REQUEST.value)
|
||||
|
||||
app_namespace = 'Assistance'
|
||||
|
||||
url_name_view = '_ticket_comment_request_view'
|
||||
|
||||
url_name_add = '_ticket_comment_request_add'
|
||||
|
||||
url_name_change = '_ticket_comment_request_change'
|
||||
|
||||
url_name_delete = '_ticket_comment_request_delete'
|
||||
|
||||
url_delete_response = reverse('Assistance:Requests')
|
@ -1,34 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import PrimaryModel, ModelAdd, ModelChange, ModelDelete
|
||||
|
||||
|
||||
|
||||
# class TicketCommentViews(
|
||||
# TestCase,
|
||||
# PrimaryModel
|
||||
# ):
|
||||
class TicketCommentViews(
|
||||
TestCase,
|
||||
ModelAdd,
|
||||
ModelChange,
|
||||
):
|
||||
|
||||
add_module = 'core.views.ticket'
|
||||
add_view = 'Add'
|
||||
|
||||
change_module = add_module
|
||||
change_view = 'Change'
|
||||
|
||||
delete_module = add_module
|
||||
delete_view = 'Delete'
|
||||
|
||||
# display_module = add_module
|
||||
# display_view = 'View'
|
||||
|
||||
# index_module = add_module
|
||||
# index_view = 'Index'
|
@ -1,192 +0,0 @@
|
||||
import django
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import TestCase, Client
|
||||
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from centurion.tests.abstract.model_permissions import ModelPermissions
|
||||
|
||||
from core.models.ticket.ticket_comment_category import TicketCommentCategory
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class TicketCommentCategoryPermissions(TestCase, ModelPermissions):
|
||||
|
||||
model = TicketCommentCategory
|
||||
|
||||
app_namespace = 'Settings'
|
||||
|
||||
url_name_view = '_ticket_comment_category_view'
|
||||
|
||||
url_name_add = '_ticket_comment_category_add'
|
||||
|
||||
url_name_change = '_ticket_comment_category_change'
|
||||
|
||||
url_name_delete = '_ticket_comment_category_delete'
|
||||
|
||||
url_delete_response = reverse('Settings:_ticket_comment_categories')
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
. create an organization that is different to item
|
||||
2. Create a category
|
||||
3. create teams with each permission: view, add, change, delete
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
|
||||
self.item = self.model.objects.create(
|
||||
organization=organization,
|
||||
name = 'manufacturerone'
|
||||
)
|
||||
|
||||
|
||||
self.url_view_kwargs = {'pk': self.item.id}
|
||||
|
||||
# self.url_add_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.add_data = {'name': 'manufacturer', 'organization': self.organization.id}
|
||||
|
||||
self.url_change_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.change_data = {'name': 'manufacturer', 'organization': self.organization.id}
|
||||
|
||||
self.url_delete_kwargs = {'pk': self.item.id}
|
||||
|
||||
self.delete_data = {'name': 'manufacturer'}
|
||||
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
|
||||
|
||||
add_permissions = Permission.objects.get(
|
||||
codename = 'add_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
add_team = Team.objects.create(
|
||||
team_name = 'add_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
add_team.permissions.set([add_permissions])
|
||||
|
||||
|
||||
|
||||
change_permissions = Permission.objects.get(
|
||||
codename = 'change_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
change_team = Team.objects.create(
|
||||
team_name = 'change_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
change_team.permissions.set([change_permissions])
|
||||
|
||||
|
||||
|
||||
delete_permissions = Permission.objects.get(
|
||||
codename = 'delete_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
delete_team = Team.objects.create(
|
||||
team_name = 'delete_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
delete_team.permissions.set([delete_permissions])
|
||||
|
||||
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
self.add_user = User.objects.create_user(username="test_user_add", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = add_team,
|
||||
user = self.add_user
|
||||
)
|
||||
|
||||
self.change_user = User.objects.create_user(username="test_user_change", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = change_team,
|
||||
user = self.change_user
|
||||
)
|
||||
|
||||
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = delete_team,
|
||||
user = self.delete_user
|
||||
)
|
||||
|
||||
|
||||
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
|
||||
|
||||
|
||||
different_organization_team = Team.objects.create(
|
||||
team_name = 'different_organization_team',
|
||||
organization = different_organization,
|
||||
)
|
||||
|
||||
different_organization_team.permissions.set([
|
||||
view_permissions,
|
||||
add_permissions,
|
||||
change_permissions,
|
||||
delete_permissions,
|
||||
])
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = different_organization_team,
|
||||
user = self.different_organization_user
|
||||
)
|
@ -1,33 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import PrimaryModel, ModelAdd, ModelChange, ModelDelete
|
||||
|
||||
|
||||
|
||||
# class TicketCommentViews(
|
||||
# TestCase,
|
||||
# PrimaryModel
|
||||
# ):
|
||||
class TicketCommentCategoryViews(
|
||||
TestCase,
|
||||
PrimaryModel
|
||||
):
|
||||
|
||||
add_module = 'core.views.ticket_comment_category'
|
||||
add_view = 'Add'
|
||||
|
||||
change_module = add_module
|
||||
change_view = 'Change'
|
||||
|
||||
delete_module = add_module
|
||||
delete_view = 'Delete'
|
||||
|
||||
display_module = add_module
|
||||
display_view = 'View'
|
||||
|
||||
index_module = add_module
|
||||
index_view = 'Index'
|
@ -1,69 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import ModelDisplay, ModelIndex
|
||||
|
||||
|
||||
|
||||
class TicketCommon(
|
||||
TestCase
|
||||
):
|
||||
|
||||
|
||||
@pytest.mark.skip(reason='to write')
|
||||
def test_ticket_field_type_opened_by(self):
|
||||
"""Ensure field is of a certain type
|
||||
|
||||
opened_by_field must be of type int
|
||||
"""
|
||||
pass
|
||||
|
||||
@pytest.mark.skip(reason='to write')
|
||||
def test_ticket_field_value_not_null_opened_by(self):
|
||||
"""Ensure field is not null
|
||||
|
||||
opened_by_field must be set and not null
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.skip(reason='to write')
|
||||
def test_ticket_field_value_auto_set_opened_by(self):
|
||||
"""Ensure field is auto set within code
|
||||
|
||||
opened_by_field must be set by code with non-tech user not being able to change
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.skip(reason='to write')
|
||||
def test_ticket_field_value_tech_set_opened_by(self):
|
||||
"""Ensure field can be set by a technician
|
||||
|
||||
opened_by_field can be set by a technician
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@pytest.mark.skip(reason='to write')
|
||||
def test_ticket_type_fields(self):
|
||||
"""Placeholder test
|
||||
|
||||
following tests to be written:
|
||||
|
||||
- only tech can change tech fields (same org)
|
||||
- non-tech cant see tech fields (same org) during creation
|
||||
- non-tech cant change tech fields (same org)
|
||||
- only tech can change tech fields (different org)
|
||||
- non-tech cant see tech fields (different org) during creation
|
||||
- non-tech cant change tech fields (different org)
|
||||
|
||||
- itsm ticket has the itsm related fields
|
||||
- non-itsm ticket does not have any itsm related fields
|
||||
|
||||
"""
|
||||
pass
|
@ -1,29 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import PrimaryModel
|
||||
|
||||
|
||||
|
||||
class TicketViews(
|
||||
TestCase,
|
||||
PrimaryModel
|
||||
):
|
||||
|
||||
add_module = 'core.views.ticket'
|
||||
add_view = 'Add'
|
||||
|
||||
change_module = add_module
|
||||
change_view = 'Change'
|
||||
|
||||
delete_module = add_module
|
||||
delete_view = 'Delete'
|
||||
|
||||
display_module = add_module
|
||||
display_view = 'View'
|
||||
|
||||
index_module = add_module
|
||||
index_view = 'Index'
|
@ -1,446 +0,0 @@
|
||||
import django
|
||||
import re
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import reverse
|
||||
from django.test import TestCase, Client
|
||||
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from access.models.tenant import Tenant as Organization
|
||||
from access.models.team import Team
|
||||
from access.models.team_user import TeamUsers
|
||||
|
||||
from centurion.tests.abstract.model_permissions import ModelPermissions, ModelPermissionsAdd
|
||||
|
||||
from project_management.models.projects import Project
|
||||
|
||||
from core.models.ticket.ticket import Ticket
|
||||
from core.models.ticket.ticket_linked_items import TicketLinkedItem
|
||||
|
||||
# from core.tests.unit.ticket.ticket_permission.field_based_permissions import ITSMTicketFieldBasedPermissions, ProjectTicketFieldBasedPermissions
|
||||
|
||||
from itam.models.device import Device
|
||||
|
||||
from settings.models.user_settings import UserSettings
|
||||
|
||||
User = django.contrib.auth.get_user_model()
|
||||
|
||||
|
||||
|
||||
class TicketLinkedItemPermissions(
|
||||
ModelPermissionsAdd,
|
||||
):
|
||||
|
||||
ticket_type:str = None
|
||||
|
||||
ticket_type_enum: int = None
|
||||
|
||||
model = TicketLinkedItem
|
||||
|
||||
app_namespace = ''
|
||||
|
||||
# url_name_view = '_ticket_request_view'
|
||||
|
||||
# url_name_add = '_ticket_request_add'
|
||||
|
||||
# url_name_change = '_ticket_request_change'
|
||||
|
||||
# url_name_delete = '_ticket_request_delete'
|
||||
|
||||
# url_delete_response = reverse('Assistance:Requests')
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(self):
|
||||
"""Setup Test
|
||||
|
||||
1. Create an organization for user and item
|
||||
. create an organization that is different to item
|
||||
2. Create a manufacturer
|
||||
3. create teams with each permission: view, add, change, delete
|
||||
4. create a user per team
|
||||
"""
|
||||
|
||||
organization = Organization.objects.create(name='test_org')
|
||||
|
||||
self.organization = organization
|
||||
|
||||
different_organization = Organization.objects.create(name='test_different_organization')
|
||||
|
||||
|
||||
add_permissions = Permission.objects.get(
|
||||
codename = 'add_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
add_team = Team.objects.create(
|
||||
team_name = 'add_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
add_team.permissions.set([add_permissions])
|
||||
|
||||
|
||||
self.add_user = User.objects.create_user(username="test_user_add", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = add_team,
|
||||
user = self.add_user
|
||||
)
|
||||
|
||||
user_settings = UserSettings.objects.get(user = self.add_user)
|
||||
user_settings.default_organization = self.organization
|
||||
user_settings.save()
|
||||
|
||||
|
||||
self.ticket = Ticket.objects.create(
|
||||
organization=organization,
|
||||
title = 'A ' + self.ticket_type + ' ticket',
|
||||
description = 'the ticket body',
|
||||
ticket_type = self.ticket_type_enum,
|
||||
opened_by = self.add_user,
|
||||
status = int(Ticket.TicketStatus.All.NEW.value)
|
||||
)
|
||||
|
||||
self.second_ticket = Ticket.objects.create(
|
||||
organization=organization,
|
||||
title = 'A second ' + self.ticket_type + ' ticket',
|
||||
description = 'the ticket body of item two',
|
||||
ticket_type = self.ticket_type_enum,
|
||||
opened_by = self.add_user,
|
||||
status = int(Ticket.TicketStatus.All.NEW.value)
|
||||
)
|
||||
|
||||
self.device = Device.objects.create(
|
||||
name = 'device-' + self.ticket_type,
|
||||
organization=organization,
|
||||
)
|
||||
|
||||
# self.project = Project.objects.create(
|
||||
# name = 'ticket permissions project name',
|
||||
# organization = organization
|
||||
# )
|
||||
|
||||
# self.project_two = Project.objects.create(
|
||||
# name = 'ticket permissions project name two',
|
||||
# organization = organization
|
||||
# )
|
||||
|
||||
|
||||
# self.url_view_kwargs = {'ticket_type': self.ticket_type, 'pk': self.item.id}
|
||||
|
||||
self.url_add_kwargs = {'ticket_type': self.ticket_type, 'ticket_id': self.ticket.id}
|
||||
|
||||
self.add_data = {
|
||||
'ticket': self.ticket.id,
|
||||
'item': self.device.id,
|
||||
'organization': self.organization.id,
|
||||
}
|
||||
|
||||
# self.url_change_kwargs = {'ticket_type': self.ticket_type, 'pk': self.item.id}
|
||||
|
||||
# self.change_data = {'title': 'an change to ticket'}
|
||||
|
||||
# self.url_delete_kwargs = {'ticket_type': self.ticket_type, 'pk': self.item.id}
|
||||
|
||||
# self.delete_data = {'title': 'a delete to ticket'}
|
||||
|
||||
|
||||
view_permissions = Permission.objects.get(
|
||||
codename = 'view_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
view_team = Team.objects.create(
|
||||
team_name = 'view_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
view_team.permissions.set([view_permissions])
|
||||
|
||||
|
||||
change_permissions = Permission.objects.get(
|
||||
codename = 'change_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
change_team = Team.objects.create(
|
||||
team_name = 'change_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
change_team.permissions.set([change_permissions])
|
||||
|
||||
self.change_team = change_team
|
||||
|
||||
|
||||
|
||||
delete_permissions = Permission.objects.get(
|
||||
codename = 'delete_' + self.model._meta.model_name,
|
||||
content_type = ContentType.objects.get(
|
||||
app_label = self.model._meta.app_label,
|
||||
model = self.model._meta.model_name,
|
||||
)
|
||||
)
|
||||
|
||||
delete_team = Team.objects.create(
|
||||
team_name = 'delete_team',
|
||||
organization = organization,
|
||||
)
|
||||
|
||||
delete_team.permissions.set([delete_permissions])
|
||||
|
||||
|
||||
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
|
||||
|
||||
|
||||
self.view_user = User.objects.create_user(username="test_user_view", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = view_team,
|
||||
user = self.view_user
|
||||
)
|
||||
|
||||
self.change_user = User.objects.create_user(username="test_user_change", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = change_team,
|
||||
user = self.change_user
|
||||
)
|
||||
|
||||
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
|
||||
teamuser = TeamUsers.objects.create(
|
||||
team = delete_team,
|
||||
user = self.delete_user
|
||||
)
|
||||
|
||||
|
||||
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
|
||||
|
||||
|
||||
different_organization_team = Team.objects.create(
|
||||
team_name = 'different_organization_team',
|
||||
organization = different_organization,
|
||||
)
|
||||
|
||||
different_organization_team.permissions.set([
|
||||
view_permissions,
|
||||
add_permissions,
|
||||
change_permissions,
|
||||
delete_permissions,
|
||||
])
|
||||
|
||||
TeamUsers.objects.create(
|
||||
team = different_organization_team,
|
||||
user = self.different_organization_user
|
||||
)
|
||||
|
||||
# Import user/permissions
|
||||
|
||||
# import_permissions = Permission.objects.get(
|
||||
# codename = 'import_' + self.model._meta.model_name,
|
||||
# content_type = ContentType.objects.get(
|
||||
# app_label = self.model._meta.app_label,
|
||||
# model = self.model._meta.model_name,
|
||||
# )
|
||||
# )
|
||||
|
||||
# import_team = Team.objects.create(
|
||||
# team_name = 'import_team',
|
||||
# organization = organization,
|
||||
# )
|
||||
|
||||
# import_team.permissions.set([change_permissions, import_permissions])
|
||||
|
||||
|
||||
# self.import_user = User.objects.create_user(username="test_user_import", password="password")
|
||||
# teamuser = TeamUsers.objects.create(
|
||||
# team = import_team,
|
||||
# user = self.import_user
|
||||
# )
|
||||
|
||||
# Triage user/permissions
|
||||
|
||||
# triage_permissions = Permission.objects.get(
|
||||
# codename = 'triage_' + self.model._meta.model_name,
|
||||
# content_type = ContentType.objects.get(
|
||||
# app_label = self.model._meta.app_label,
|
||||
# model = self.model._meta.model_name,
|
||||
# )
|
||||
# )
|
||||
|
||||
# triage_team = Team.objects.create(
|
||||
# team_name = 'triage_team',
|
||||
# organization = organization,
|
||||
# )
|
||||
|
||||
# triage_team.permissions.set([change_permissions, triage_permissions])
|
||||
|
||||
|
||||
# self.triage_user = User.objects.create_user(username="test_user_triage", password="password")
|
||||
# teamuser = TeamUsers.objects.create(
|
||||
# team = triage_team,
|
||||
# user = self.triage_user
|
||||
# )
|
||||
|
||||
|
||||
|
||||
class ITSMTicketLinkedItemPermissions(
|
||||
TicketLinkedItemPermissions,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ProjectTicketLinkedItemPermissions(
|
||||
TicketLinkedItemPermissions,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ChangeTicketLinkedItemPermissions(ITSMTicketLinkedItemPermissions, TestCase):
|
||||
|
||||
ticket_type = 'change'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.CHANGE.value)
|
||||
|
||||
app_namespace = ''
|
||||
|
||||
# url_name_view = '_ticket_change_view'
|
||||
|
||||
url_name_add = '_ticket_linked_item_add'
|
||||
|
||||
# url_name_change = '_ticket_change_change'
|
||||
|
||||
# url_name_delete = '_ticket_change_delete'
|
||||
|
||||
# url_delete_response = reverse('ITIM:Changes')
|
||||
|
||||
|
||||
|
||||
class IncidentTicketLinkedItemPermissions(ITSMTicketLinkedItemPermissions, TestCase):
|
||||
|
||||
ticket_type = 'incident'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.INCIDENT.value)
|
||||
|
||||
# app_namespace = 'ITIM'
|
||||
|
||||
# url_name_view = '_ticket_incident_view'
|
||||
|
||||
url_name_add = '_ticket_linked_item_add'
|
||||
|
||||
# url_name_change = '_ticket_incident_change'
|
||||
|
||||
# url_name_delete = '_ticket_incident_delete'
|
||||
|
||||
# url_delete_response = reverse('ITIM:Incidents')
|
||||
|
||||
|
||||
|
||||
class ProblemTicketLinkedItemPermissions(ITSMTicketLinkedItemPermissions, TestCase):
|
||||
|
||||
ticket_type = 'problem'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.PROBLEM.value)
|
||||
|
||||
# app_namespace = 'ITIM'
|
||||
|
||||
# url_name_view = '_ticket_problem_view'
|
||||
|
||||
url_name_add = '_ticket_linked_item_add'
|
||||
|
||||
# url_name_change = '_ticket_problem_change'
|
||||
|
||||
# url_name_delete = '_ticket_problem_delete'
|
||||
|
||||
# url_delete_response = reverse('ITIM:Problems')
|
||||
|
||||
|
||||
|
||||
class ProjectTaskTicketLinkedItemPermissions(ProjectTicketLinkedItemPermissions, TestCase):
|
||||
|
||||
ticket_type = 'project_task'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.PROJECT_TASK.value)
|
||||
|
||||
# app_namespace = 'Project Management'
|
||||
|
||||
# url_name_view = '_project_task_view'
|
||||
|
||||
url_name_add = '_ticket_linked_item_add'
|
||||
|
||||
# url_name_change = '_project_task_change'
|
||||
|
||||
# url_name_delete = '_project_task_delete'
|
||||
|
||||
|
||||
|
||||
|
||||
# @classmethod
|
||||
# def setUpTestData(self):
|
||||
# """Setup Test
|
||||
|
||||
# 1. Create an organization for user and item
|
||||
# . create an organization that is different to item
|
||||
# 2. Create a manufacturer
|
||||
# 3. create teams with each permission: view, add, change, delete
|
||||
# 4. create a user per team
|
||||
# """
|
||||
|
||||
# super().setUpTestData()
|
||||
|
||||
# self.item = self.model.objects.create(
|
||||
# organization = self.organization,
|
||||
# title = 'Amended ' + self.ticket_type + ' ticket',
|
||||
# description = 'the ticket body',
|
||||
# ticket_type = int(Ticket.TicketType.REQUEST.value),
|
||||
# opened_by = self.add_user,
|
||||
# status = int(Ticket.TicketStatus.All.NEW.value),
|
||||
# project = self.project
|
||||
# )
|
||||
|
||||
# self.url_add_kwargs = {'project_id': self.project.id, 'ticket_type': self.ticket_type}
|
||||
|
||||
# self.url_change_kwargs = {'project_id': self.project.id, 'ticket_type': self.ticket_type, 'pk': self.item.id}
|
||||
|
||||
# self.url_delete_kwargs = {'project_id': self.project.id, 'ticket_type': self.ticket_type, 'pk': self.project.id}
|
||||
|
||||
# # self.url_delete_kwargs = {'pk': self.project.id}
|
||||
|
||||
# self.url_view_kwargs = {'project_id': self.project.id, 'ticket_type': self.ticket_type, 'pk': self.item.id}
|
||||
|
||||
# self.url_delete_response = reverse('Project Management:_project_view', kwargs={'pk': self.project.id})
|
||||
|
||||
|
||||
|
||||
class RequestTicketLinkedItemPermissions(ITSMTicketLinkedItemPermissions, TestCase):
|
||||
|
||||
ticket_type = 'request'
|
||||
|
||||
ticket_type_enum: int = int(Ticket.TicketType.REQUEST.value)
|
||||
|
||||
# app_namespace = ''
|
||||
|
||||
# url_name_view = '_ticket_request_view'
|
||||
|
||||
url_name_add = '_ticket_linked_item_add'
|
||||
|
||||
# url_name_change = '_ticket_request_change'
|
||||
|
||||
# url_name_delete = '_ticket_request_delete'
|
||||
|
||||
# url_delete_response = reverse('Assistance:Requests')
|
@ -1,29 +0,0 @@
|
||||
import pytest
|
||||
import unittest
|
||||
import requests
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from centurion.tests.abstract.models import ModelAdd, PrimaryModel
|
||||
|
||||
|
||||
|
||||
class TicketLinkedItemViews(
|
||||
TestCase,
|
||||
ModelAdd
|
||||
):
|
||||
|
||||
add_module = 'core.views.ticket_linked_item'
|
||||
add_view = 'Add'
|
||||
|
||||
change_module = add_module
|
||||
change_view = 'Change'
|
||||
|
||||
delete_module = add_module
|
||||
delete_view = 'Delete'
|
||||
|
||||
display_module = add_module
|
||||
display_view = 'View'
|
||||
|
||||
index_module = add_module
|
||||
index_view = 'Index'
|
@ -1,72 +0,0 @@
|
||||
from django.views import generic
|
||||
|
||||
from access.mixin import OrganizationPermission
|
||||
|
||||
from django_celery_results.models import TaskResult
|
||||
|
||||
|
||||
|
||||
class Index(OrganizationPermission, generic.ListView):
|
||||
|
||||
context_object_name = "task_results"
|
||||
|
||||
fields = [
|
||||
"task_id",
|
||||
'task_name',
|
||||
'status',
|
||||
'date_created',
|
||||
'date_done',
|
||||
]
|
||||
|
||||
model = TaskResult
|
||||
|
||||
permission_required = [
|
||||
'django_celery_results.view_taskresult',
|
||||
]
|
||||
|
||||
template_name = 'celery_log_index.html.j2'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Background Task Results'
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_device_model_view', args=(self.kwargs['pk'],))
|
||||
|
||||
|
||||
|
||||
class View(OrganizationPermission, generic.UpdateView):
|
||||
|
||||
context_object_name = "task_result"
|
||||
|
||||
fields = [
|
||||
"task_id",
|
||||
'task_name',
|
||||
'status',
|
||||
'task_args',
|
||||
]
|
||||
|
||||
model = TaskResult
|
||||
|
||||
permission_required = [
|
||||
'django_celery_results.view_taskresult',
|
||||
]
|
||||
|
||||
template_name = 'celery_log.html.j2'
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = f"Task {self.object.task_id}"
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
pass
|
@ -1,236 +0,0 @@
|
||||
from django.template import Template, Context
|
||||
from django.utils.html import escape
|
||||
from django.views import generic
|
||||
|
||||
from access.mixin import OrganizationPermission
|
||||
|
||||
from core.exceptions import MissingAttribute
|
||||
|
||||
from settings.models.external_link import ExternalLink
|
||||
from settings.models.user_settings import UserSettings
|
||||
|
||||
|
||||
|
||||
class View(OrganizationPermission):
|
||||
""" Abstract class common to all views
|
||||
|
||||
## Functions
|
||||
|
||||
- `get_dynamic_permissions()` A function to build and return the permissions for the view
|
||||
|
||||
!!! Danger
|
||||
Don't directly use this class within your view as it's already assigned to the views that require it.
|
||||
"""
|
||||
|
||||
template_name:str = 'form.html.j2'
|
||||
|
||||
|
||||
def get_form_kwargs(self) -> dict:
|
||||
""" Fetch kwargs for form
|
||||
|
||||
Returns:
|
||||
dict: kwargs used in fetching form
|
||||
"""
|
||||
|
||||
kwargs = super().get_form_kwargs()
|
||||
|
||||
if self.form_class:
|
||||
|
||||
kwargs.update({'user': self.request.user})
|
||||
|
||||
return kwargs
|
||||
|
||||
|
||||
|
||||
class AddView(View, generic.CreateView):
|
||||
|
||||
template_name:str = 'form.html.j2'
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
return {
|
||||
'organization': UserSettings.objects.get(user = self.request.user).default_organization
|
||||
}
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'New ' + self.model._meta.verbose_name
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class ChangeView(View, generic.UpdateView):
|
||||
|
||||
template_name:str = 'form.html.j2'
|
||||
|
||||
# ToDo: on migrating all views to seperate display and change views, external_links will not be required in `ChangView`
|
||||
def get_context_data(self, **kwargs):
|
||||
""" Get template context
|
||||
|
||||
For items that have the ability to have external links, this function
|
||||
adds the external link details to the context.
|
||||
|
||||
!!! Danger "Requirement"
|
||||
This function may be overridden with the caveat that this function is still called.
|
||||
by the overriding function. i.e. `super().get_context_data(skwargs)`
|
||||
|
||||
!!! note
|
||||
The adding of `external_links` within this view is scheduled to be removed.
|
||||
|
||||
Returns:
|
||||
(dict): Context for the template to use inclusive of 'external_links'
|
||||
"""
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
external_links_query = None
|
||||
|
||||
if 'tab' in self.request.GET:
|
||||
|
||||
context['open_tab'] = str(self.request.GET.get("tab")).lower()
|
||||
|
||||
else:
|
||||
context['open_tab'] = None
|
||||
|
||||
|
||||
if self.model._meta.model_name == 'cluster':
|
||||
|
||||
external_links_query = ExternalLink.objects.filter(cluster=True)
|
||||
|
||||
elif self.model._meta.model_name == 'device':
|
||||
|
||||
external_links_query = ExternalLink.objects.filter(devices=True)
|
||||
|
||||
elif self.model._meta.model_name == 'software':
|
||||
|
||||
external_links_query = ExternalLink.objects.filter(software=True)
|
||||
|
||||
|
||||
if external_links_query:
|
||||
|
||||
external_links: list = []
|
||||
|
||||
user_context = Context(context)
|
||||
|
||||
for external_link in external_links_query:
|
||||
|
||||
user_string = Template(external_link)
|
||||
external_link_context: dict = {
|
||||
'name': escape(external_link.name),
|
||||
'link': escape(user_string.render(user_context)),
|
||||
}
|
||||
|
||||
if external_link.colour:
|
||||
|
||||
external_link_context.update({'colour': external_link.colour })
|
||||
external_links += [ external_link_context ]
|
||||
|
||||
context['external_links'] = external_links
|
||||
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
return {
|
||||
'organization': UserSettings.objects.get(user = self.request.user).default_organization
|
||||
}
|
||||
|
||||
|
||||
class DeleteView(OrganizationPermission, generic.DeleteView):
|
||||
|
||||
template_name:str = 'form.html.j2'
|
||||
|
||||
|
||||
|
||||
class DisplayView(OrganizationPermission, generic.DetailView):
|
||||
""" A View used for displaying arbitrary data """
|
||||
|
||||
template_name:str = 'form.html.j2'
|
||||
|
||||
|
||||
# ToDo: on migrating all views to seperate display and change views, external_links will not be required in `ChangView`
|
||||
def get_context_data(self, **kwargs):
|
||||
""" Get template context
|
||||
|
||||
For items that have the ability to have external links, this function
|
||||
adds the external link details to the context.
|
||||
|
||||
!!! Danger "Requirement"
|
||||
This function may be overridden with the caveat that this function is still called.
|
||||
by the overriding function. i.e. `super().get_context_data(skwargs)`
|
||||
|
||||
Returns:
|
||||
(dict): Context for the template to use inclusive of 'external_links'
|
||||
"""
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
external_links_query = None
|
||||
|
||||
|
||||
if self.model._meta.model_name == 'device':
|
||||
|
||||
external_links_query = ExternalLink.objects.filter(devices=True)
|
||||
|
||||
elif self.model._meta.model_name == 'software':
|
||||
|
||||
external_links_query = ExternalLink.objects.filter(software=True)
|
||||
|
||||
|
||||
if external_links_query:
|
||||
|
||||
external_links: list = []
|
||||
|
||||
user_context = Context(context)
|
||||
|
||||
for external_link in external_links_query:
|
||||
|
||||
user_string = Template(external_link)
|
||||
external_link_context: dict = {
|
||||
'name': escape(external_link.name),
|
||||
'link': escape(user_string.render(user_context)),
|
||||
}
|
||||
|
||||
if external_link.colour:
|
||||
|
||||
external_link_context.update({'colour': external_link.colour })
|
||||
external_links += [ external_link_context ]
|
||||
|
||||
context['external_links'] = external_links
|
||||
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class IndexView(View, generic.ListView):
|
||||
|
||||
model = None
|
||||
""" Model the view is for
|
||||
|
||||
Leaving this value unset will prevent the item from showing up within the navigation menu
|
||||
"""
|
||||
|
||||
template_name:str = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
if not self.model:
|
||||
|
||||
raise MissingAttribute('Model is required for view')
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = self.model._meta.verbose_name_plural
|
||||
|
||||
return context
|
@ -1,83 +0,0 @@
|
||||
from django.urls import reverse
|
||||
from django.views import generic
|
||||
|
||||
from django_celery_results.models import TaskResult
|
||||
|
||||
from access.mixin import OrganizationPermission
|
||||
|
||||
from core.forms.related_ticket import RelatedTicketForm
|
||||
from core.models.ticket.ticket import RelatedTickets
|
||||
from core.views.common import AddView, ChangeView, DeleteView, IndexView
|
||||
|
||||
from settings.models.user_settings import UserSettings
|
||||
|
||||
|
||||
|
||||
class Add(AddView):
|
||||
|
||||
form_class = RelatedTicketForm
|
||||
|
||||
model = RelatedTickets
|
||||
|
||||
permission_required = [
|
||||
'itam.add_device',
|
||||
]
|
||||
|
||||
template_name = 'form.html.j2'
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
initial_values: dict = {
|
||||
'organization': UserSettings.objects.get(user = self.request.user).default_organization,
|
||||
'from_ticket_id': self.kwargs['ticket_id'],
|
||||
}
|
||||
|
||||
return initial_values
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
return reverse('Assistance:_ticket_request_view', args=(self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
return reverse('Project Management:_project_task_view', args=(self.object.from_ticket_id.project.id, self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
else:
|
||||
|
||||
return reverse('ITIM:_ticket_' + str(self.kwargs['ticket_type']).lower() + '_view', args=(self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Ticket Comment'
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class Delete(DeleteView):
|
||||
|
||||
model = RelatedTickets
|
||||
|
||||
permission_required = [
|
||||
'itim.delete_cluster',
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Delete ' + str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('ITIM:Clusters')
|
@ -1,341 +0,0 @@
|
||||
from django.http import Http404
|
||||
from django.urls import reverse
|
||||
from django.views import generic
|
||||
|
||||
from django_celery_results.models import TaskResult
|
||||
|
||||
from access.mixin import OrganizationPermission
|
||||
|
||||
from core.forms.ticket import DetailForm, TicketForm
|
||||
from core.models.ticket.ticket import Ticket
|
||||
from core.views.common import AddView, ChangeView, DeleteView, IndexView
|
||||
|
||||
from settings.models.user_settings import UserSettings
|
||||
|
||||
|
||||
|
||||
class Add(AddView):
|
||||
|
||||
form_class = TicketForm
|
||||
|
||||
model = Ticket
|
||||
|
||||
|
||||
def get_dynamic_permissions(self):
|
||||
|
||||
return [
|
||||
str('core.add_ticket_' + self.kwargs['ticket_type']),
|
||||
]
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
initial = super().get_initial()
|
||||
|
||||
initial.update({
|
||||
'type_ticket': self.kwargs['ticket_type'],
|
||||
})
|
||||
|
||||
if self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
initial.update({
|
||||
'project': int(self.kwargs['project_id'])
|
||||
})
|
||||
|
||||
return initial
|
||||
|
||||
|
||||
def form_valid(self, form):
|
||||
|
||||
created: bool = False
|
||||
|
||||
if form.instance.id is None:
|
||||
|
||||
created = True
|
||||
|
||||
val = super().form_valid(form)
|
||||
|
||||
if created:
|
||||
|
||||
form.instance.subscribed_users.add(form.instance.opened_by)
|
||||
|
||||
return val
|
||||
|
||||
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['request'] = self.request
|
||||
return kwargs
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
return reverse('Assistance:_ticket_request_view', args=(self.kwargs['ticket_type'],self.object.id,))
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
return reverse('Project Management:_project_task_view', args=(self.kwargs['project_id'], self.kwargs['ticket_type'],self.object.id,))
|
||||
|
||||
else:
|
||||
|
||||
return reverse('ITIM:_ticket_' + str(self.kwargs['ticket_type']).lower() + '_view', args=(self.kwargs['ticket_type'],self.object.id,))
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'New Ticket'
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class Change(ChangeView):
|
||||
|
||||
form_class = TicketForm
|
||||
|
||||
model = Ticket
|
||||
|
||||
|
||||
def get_dynamic_permissions(self):
|
||||
|
||||
return [
|
||||
str('core.change_ticket_' + self.kwargs['ticket_type']),
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['request'] = self.request
|
||||
return kwargs
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
initial = super().get_initial()
|
||||
|
||||
initial.update({
|
||||
'type_ticket': self.kwargs['ticket_type'],
|
||||
})
|
||||
|
||||
if self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
initial.update({
|
||||
'project': int(self.kwargs['project_id'])
|
||||
})
|
||||
|
||||
return initial
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
return reverse('Assistance:_ticket_request_view', args=(self.kwargs['ticket_type'],self.object.id,))
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
return reverse('Project Management:_project_task_view', args=(self.kwargs['project_id'], self.kwargs['ticket_type'],self.object.id,))
|
||||
|
||||
else:
|
||||
|
||||
return reverse('ITIM:_ticket_' + str(self.kwargs['ticket_type']).lower() + '_view', args=(self.kwargs['ticket_type'],self.object.id,))
|
||||
|
||||
|
||||
class Delete(DeleteView):
|
||||
|
||||
model = Ticket
|
||||
|
||||
|
||||
def get_dynamic_permissions(self):
|
||||
|
||||
return [
|
||||
str('core.delete_ticket_' + self.kwargs['ticket_type']),
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Delete ' + str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
return reverse('Assistance:Requests')
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
return reverse('Project Management:_project_view', kwargs={'pk': self.object.id})
|
||||
|
||||
else:
|
||||
|
||||
if self.kwargs['ticket_type'] == 'change':
|
||||
path = 'Changes'
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'incident':
|
||||
path = 'Incidents'
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'problem':
|
||||
path = 'Problems'
|
||||
|
||||
|
||||
return reverse('ITIM:' + path)
|
||||
|
||||
|
||||
|
||||
class Index(OrganizationPermission, generic.ListView):
|
||||
|
||||
context_object_name = "tickets"
|
||||
|
||||
fields = [
|
||||
"id",
|
||||
'title',
|
||||
'status',
|
||||
'date_created',
|
||||
]
|
||||
|
||||
model = Ticket
|
||||
|
||||
template_name = 'core/ticket/index.html.j2'
|
||||
|
||||
|
||||
def get_dynamic_permissions(self):
|
||||
|
||||
return [
|
||||
str('core.view_ticket_' + self.kwargs['ticket_type']),
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
context['new_ticket_url'] = reverse('Assistance:_ticket_request_add', args=(self.kwargs['ticket_type'],))
|
||||
|
||||
else:
|
||||
|
||||
context['new_ticket_url'] = reverse(str('ITIM:_ticket_' + self.kwargs['ticket_type'] + '_add'), args=(self.kwargs['ticket_type'],))
|
||||
|
||||
|
||||
context['ticket_type'] = self.kwargs['ticket_type']
|
||||
|
||||
context['content_title'] = 'Tickets'
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_queryset(self):
|
||||
|
||||
if not hasattr(Ticket.TicketType, str(self.kwargs['ticket_type']).upper()):
|
||||
raise Http404
|
||||
|
||||
queryset = super().get_queryset()
|
||||
|
||||
queryset = queryset.filter(
|
||||
ticket_type = Ticket.TicketType[str(self.kwargs['ticket_type']).upper()]
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_device_model_view', args=(self.kwargs['pk'],))
|
||||
|
||||
|
||||
|
||||
class View(ChangeView):
|
||||
|
||||
model = Ticket
|
||||
|
||||
template_name = 'core/ticket.html.j2'
|
||||
|
||||
form_class = DetailForm
|
||||
|
||||
context_object_name = "ticket"
|
||||
|
||||
|
||||
def get_dynamic_permissions(self):
|
||||
|
||||
return [
|
||||
str('core.view_ticket_' + self.kwargs['ticket_type']),
|
||||
]
|
||||
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
context['ticket_type'] = self.kwargs['ticket_type']
|
||||
|
||||
url_kwargs = { 'ticket_type': self.kwargs['ticket_type'], 'pk': self.kwargs['pk']}
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
path = 'Assistance:_ticket_request_change'
|
||||
|
||||
context['model_delete_url'] = reverse('Assistance:_ticket_' + self.kwargs['ticket_type'] + '_delete', kwargs=url_kwargs)
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
path = 'Project Management:_project_task_change'
|
||||
|
||||
url_kwargs = { 'project_id': self.kwargs['project_id'],'ticket_type': self.kwargs['ticket_type'], 'pk': self.kwargs['pk']}
|
||||
|
||||
context['model_delete_url'] = reverse('Project Management:_project_task_delete', kwargs=url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
comment_path = 'ITIM:_ticket_comment_' + self.kwargs['ticket_type']
|
||||
|
||||
if self.kwargs['ticket_type'] == 'change':
|
||||
|
||||
path = 'ITIM:_ticket_change_change'
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'incident':
|
||||
|
||||
path = 'ITIM:_ticket_incident_change'
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'problem':
|
||||
|
||||
path = 'ITIM:_ticket_problem_change'
|
||||
|
||||
|
||||
context['model_delete_url'] = reverse('ITIM:_ticket_' + self.kwargs['ticket_type'] + '_delete', kwargs=url_kwargs)
|
||||
|
||||
context['edit_url'] = reverse(
|
||||
path,
|
||||
kwargs = url_kwargs,
|
||||
) # /assistance/ticket/{{ ticket_type }}/{{ ticket.id }}
|
||||
|
||||
|
||||
context['content_title'] = self.object.title
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
return {
|
||||
'type_ticket': self.kwargs['ticket_type'],
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
from django.urls import reverse
|
||||
|
||||
from core.forms.comment import AddNoteForm
|
||||
from core.forms.ticket_categories import DetailForm, TicketCategory, TicketCategoryForm
|
||||
|
||||
from core.models.notes import Notes
|
||||
from core.views.common import AddView, ChangeView, DeleteView, IndexView
|
||||
|
||||
|
||||
|
||||
class Add(AddView):
|
||||
|
||||
form_class = TicketCategoryForm
|
||||
|
||||
model = TicketCategory
|
||||
|
||||
permission_required = [
|
||||
'core.add_ticketcategory',
|
||||
]
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
initial = super().get_initial()
|
||||
|
||||
if 'pk' in self.kwargs:
|
||||
|
||||
if self.kwargs['pk']:
|
||||
|
||||
initial.update({'parent': self.kwargs['pk']})
|
||||
|
||||
self.model.parent.field.hidden = True
|
||||
|
||||
return initial
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_categories')
|
||||
|
||||
|
||||
|
||||
class Change(ChangeView):
|
||||
|
||||
form_class = TicketCategoryForm
|
||||
|
||||
model = TicketCategory
|
||||
|
||||
permission_required = [
|
||||
'core.change_ticketcategory',
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_category_view', args=(self.kwargs['pk'],))
|
||||
|
||||
|
||||
|
||||
class Delete(DeleteView):
|
||||
|
||||
model = TicketCategory
|
||||
|
||||
permission_required = [
|
||||
'core.delete_ticketcategory',
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Delete ' + str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_categories')
|
||||
|
||||
|
||||
|
||||
class Index(IndexView):
|
||||
|
||||
context_object_name = "items"
|
||||
|
||||
model = TicketCategory
|
||||
|
||||
paginate_by = 10
|
||||
|
||||
permission_required = [
|
||||
'core.view_ticketcategory'
|
||||
]
|
||||
|
||||
template_name = 'core/index_ticket_categories.html.j2'
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['model_docs_path'] = self.model._meta.app_label + '/' + self.model._meta.model_name
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class View(ChangeView):
|
||||
|
||||
context_object_name = "ticket_categories"
|
||||
|
||||
form_class = DetailForm
|
||||
|
||||
model = TicketCategory
|
||||
|
||||
permission_required = [
|
||||
'core.view_ticketcategory',
|
||||
]
|
||||
|
||||
template_name = 'core/ticket_category.html.j2'
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['notes_form'] = AddNoteForm(prefix='note')
|
||||
context['notes'] = Notes.objects.filter(service=self.kwargs['pk'])
|
||||
|
||||
context['model_pk'] = self.kwargs['pk']
|
||||
context['model_name'] = self.model._meta.model_name
|
||||
|
||||
context['model_delete_url'] = reverse('Settings:_ticket_category_delete', kwargs={'pk': self.kwargs['pk']})
|
||||
|
||||
|
||||
context['content_title'] = self.object.name
|
||||
|
||||
return context
|
||||
|
||||
|
||||
# def post(self, request, *args, **kwargs):
|
||||
|
||||
# item = Cluster.objects.get(pk=self.kwargs['pk'])
|
||||
|
||||
# notes = AddNoteForm(request.POST, prefix='note')
|
||||
|
||||
# if notes.is_bound and notes.is_valid() and notes.instance.note != '':
|
||||
|
||||
# notes.instance.service = item
|
||||
|
||||
# notes.instance.organization = item.organization
|
||||
|
||||
# notes.save()
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_category_view', kwargs={'pk': self.kwargs['pk']})
|
@ -1,156 +0,0 @@
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import Http404
|
||||
from django.urls import reverse
|
||||
from django.views import generic
|
||||
|
||||
from django_celery_results.models import TaskResult
|
||||
|
||||
from access.mixin import OrganizationPermission
|
||||
|
||||
from core.forms.ticket_comment import CommentForm, DetailForm
|
||||
from core.models.ticket.ticket_comment import TicketComment, Ticket
|
||||
from core.views.common import AddView, ChangeView, DeleteView, IndexView
|
||||
|
||||
from settings.models.user_settings import UserSettings
|
||||
|
||||
|
||||
|
||||
class Add(AddView):
|
||||
|
||||
form_class = CommentForm
|
||||
|
||||
model = TicketComment
|
||||
|
||||
parent_model = Ticket
|
||||
|
||||
parent_model_pk_kwarg = 'ticket_id'
|
||||
|
||||
template_name = 'form.html.j2'
|
||||
|
||||
|
||||
def get_dynamic_permissions(self):
|
||||
|
||||
if self.request.user.is_authenticated:
|
||||
|
||||
try:
|
||||
|
||||
ticket = Ticket.objects.get(pk=int(self.kwargs['ticket_id']))
|
||||
|
||||
if ticket.opened_by.id == self.request.user.id:
|
||||
|
||||
return []
|
||||
|
||||
except ObjectDoesNotExist:
|
||||
|
||||
pass
|
||||
|
||||
return [
|
||||
str('core.add_ticketcomment'),
|
||||
]
|
||||
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['request'] = self.request
|
||||
return kwargs
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
initial_values: dict = {
|
||||
'organization': UserSettings.objects.get(user = self.request.user).default_organization,
|
||||
'type_ticket': self.kwargs['ticket_type'],
|
||||
'ticket': self.kwargs['ticket_id'],
|
||||
}
|
||||
|
||||
if 'comment_type' in self.request.GET:
|
||||
|
||||
initial_values.update({
|
||||
'qs_comment_type': self.request.GET['comment_type']
|
||||
})
|
||||
|
||||
if 'parent_id' in self.kwargs:
|
||||
|
||||
initial_values.update({
|
||||
'parent': self.kwargs['parent_id']
|
||||
})
|
||||
|
||||
return initial_values
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
return reverse('Assistance:_ticket_request_view', args=(self.kwargs['ticket_type'],self.kwargs['ticket_id']))
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
return reverse('Project Management:_project_task_view', args=(self.object.ticket.project.id, self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
return reverse(
|
||||
'ITIM:_ticket_' + self.kwargs['ticket_type'] + '_view',
|
||||
kwargs={'ticket_type': self.kwargs['ticket_type'], 'pk': self.kwargs['ticket_id']},
|
||||
)
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Ticket Comment'
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class Change(ChangeView):
|
||||
|
||||
form_class = CommentForm
|
||||
|
||||
model = TicketComment
|
||||
|
||||
|
||||
def get_dynamic_permissions(self):
|
||||
|
||||
try:
|
||||
|
||||
if (
|
||||
self.request.user.is_authenticated and
|
||||
self.get_object().user.id == self.request.user.id
|
||||
):
|
||||
|
||||
return []
|
||||
|
||||
except Http404: # Although the model not found, permissions must return HTTP/403 for authenticated user
|
||||
|
||||
pass
|
||||
|
||||
return [
|
||||
str('core.change_ticketcomment'),
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['request'] = self.request
|
||||
return kwargs
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
return {
|
||||
'type_ticket': self.kwargs['ticket_type'],
|
||||
}
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Assistance:_ticket_request_view', args=(self.kwargs['ticket_type'], self.kwargs['ticket_id'],))
|
@ -1,168 +0,0 @@
|
||||
from django.urls import reverse
|
||||
|
||||
from core.forms.comment import AddNoteForm
|
||||
from core.forms.ticket_comment_category import DetailForm, TicketCommentCategory, TicketCommentCategoryForm
|
||||
|
||||
from core.models.notes import Notes
|
||||
from core.views.common import AddView, ChangeView, DeleteView, IndexView
|
||||
|
||||
|
||||
|
||||
class Add(AddView):
|
||||
|
||||
form_class = TicketCommentCategoryForm
|
||||
|
||||
model = TicketCommentCategory
|
||||
|
||||
permission_required = [
|
||||
'core.add_ticketcommentcategory',
|
||||
]
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
initial = super().get_initial()
|
||||
|
||||
if 'pk' in self.kwargs:
|
||||
|
||||
if self.kwargs['pk']:
|
||||
|
||||
initial.update({'parent': self.kwargs['pk']})
|
||||
|
||||
self.model.parent.field.hidden = True
|
||||
|
||||
return initial
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_comment_categories')
|
||||
|
||||
|
||||
|
||||
class Change(ChangeView):
|
||||
|
||||
form_class = TicketCommentCategoryForm
|
||||
|
||||
model = TicketCommentCategory
|
||||
|
||||
permission_required = [
|
||||
'core.change_ticketcommentcategory',
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_comment_category_view', args=(self.kwargs['pk'],))
|
||||
|
||||
|
||||
|
||||
class Delete(DeleteView):
|
||||
|
||||
model = TicketCommentCategory
|
||||
|
||||
permission_required = [
|
||||
'core.delete_ticketcommentcategory',
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Delete ' + str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_comment_categories')
|
||||
|
||||
|
||||
|
||||
class Index(IndexView):
|
||||
|
||||
context_object_name = "items"
|
||||
|
||||
model = TicketCommentCategory
|
||||
|
||||
paginate_by = 10
|
||||
|
||||
permission_required = [
|
||||
'core.view_ticketcommentcategory'
|
||||
]
|
||||
|
||||
template_name = 'core/index_ticket_comment_categories.html.j2'
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['model_docs_path'] = self.model._meta.app_label + '/ticket_comment_category'
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class View(ChangeView):
|
||||
|
||||
context_object_name = "ticket_categories"
|
||||
|
||||
form_class = DetailForm
|
||||
|
||||
model = TicketCommentCategory
|
||||
|
||||
permission_required = [
|
||||
'core.view_ticketcommentcategory',
|
||||
]
|
||||
|
||||
template_name = 'core/ticket_comment_category.html.j2'
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['notes_form'] = AddNoteForm(prefix='note')
|
||||
context['notes'] = Notes.objects.filter(service=self.kwargs['pk'])
|
||||
|
||||
context['model_pk'] = self.kwargs['pk']
|
||||
context['model_name'] = self.model._meta.model_name
|
||||
|
||||
context['model_delete_url'] = reverse('Settings:_ticket_comment_category_delete', kwargs={'pk': self.kwargs['pk']})
|
||||
|
||||
|
||||
context['content_title'] = self.object.name
|
||||
|
||||
return context
|
||||
|
||||
|
||||
# def post(self, request, *args, **kwargs):
|
||||
|
||||
# item = Cluster.objects.get(pk=self.kwargs['pk'])
|
||||
|
||||
# notes = AddNoteForm(request.POST, prefix='note')
|
||||
|
||||
# if notes.is_bound and notes.is_valid() and notes.instance.note != '':
|
||||
|
||||
# notes.instance.service = item
|
||||
|
||||
# notes.instance.organization = item.organization
|
||||
|
||||
# notes.save()
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
return reverse('Settings:_ticket_comment_category_view', kwargs={'pk': self.kwargs['pk']})
|
@ -1,92 +0,0 @@
|
||||
from django.urls import reverse
|
||||
from django.views import generic
|
||||
|
||||
from django_celery_results.models import TaskResult
|
||||
|
||||
from access.mixin import OrganizationPermission
|
||||
|
||||
from core.forms.ticket_linked_item import TicketLinkedItem, TicketLinkedItemForm
|
||||
from core.views.common import AddView, ChangeView, DeleteView, IndexView
|
||||
|
||||
from settings.models.user_settings import UserSettings
|
||||
|
||||
|
||||
|
||||
class Add(AddView):
|
||||
|
||||
form_class = TicketLinkedItemForm
|
||||
|
||||
model = TicketLinkedItem
|
||||
|
||||
permission_required = [
|
||||
'core.add_ticketlinkeditem',
|
||||
]
|
||||
|
||||
template_name = 'form.html.j2'
|
||||
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
initial_values: dict = {
|
||||
'organization': UserSettings.objects.get(user = self.request.user).default_organization,
|
||||
'ticket': self.kwargs['ticket_id'],
|
||||
}
|
||||
|
||||
return initial_values
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
return reverse('Assistance:_ticket_request_view', args=(self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
return reverse('Project Management:_project_task_view', args=(self.object.from_ticket_id.project.id, self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
else:
|
||||
|
||||
return reverse('ITIM:_ticket_' + str(self.kwargs['ticket_type']).lower() + '_view', args=(self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Ticket Linked Item'
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class Delete(DeleteView):
|
||||
|
||||
model = TicketLinkedItem
|
||||
|
||||
permission_required = [
|
||||
'itim.delete_cluster',
|
||||
]
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['content_title'] = 'Delete ' + str(self.object)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
|
||||
if self.kwargs['ticket_type'] == 'request':
|
||||
|
||||
return reverse('Assistance:_ticket_request_view', args=(self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
elif self.kwargs['ticket_type'] == 'project_task':
|
||||
|
||||
return reverse('Project Management:_project_task_view', args=(self.object.from_ticket_id.project.id, self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|
||||
|
||||
else:
|
||||
|
||||
return reverse('ITIM:_ticket_' + str(self.kwargs['ticket_type']).lower() + '_view', args=(self.kwargs['ticket_type'],self.kwargs['ticket_id'],))
|