mirror of https://github.com/jumpserver/jumpserver
				
				
				
			perf: 去掉工单重新打开状态
							parent
							
								
									681cecc52b
								
							
						
					
					
						commit
						d3d89b0853
					
				| 
						 | 
					@ -16,7 +16,6 @@ class TicketType(TextChoices):
 | 
				
			||||||
class TicketState(TextChoices):
 | 
					class TicketState(TextChoices):
 | 
				
			||||||
    pending = 'pending', _('Open')
 | 
					    pending = 'pending', _('Open')
 | 
				
			||||||
    closed = 'closed', _("Cancel")
 | 
					    closed = 'closed', _("Cancel")
 | 
				
			||||||
    reopen = 'reopen', _("Reopen")
 | 
					 | 
				
			||||||
    approved = 'approved', _('Approved')
 | 
					    approved = 'approved', _('Approved')
 | 
				
			||||||
    rejected = 'rejected', _('Rejected')
 | 
					    rejected = 'rejected', _('Rejected')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +28,6 @@ class TicketStatus(TextChoices):
 | 
				
			||||||
class StepState(TextChoices):
 | 
					class StepState(TextChoices):
 | 
				
			||||||
    pending = 'pending', _('Pending')
 | 
					    pending = 'pending', _('Pending')
 | 
				
			||||||
    closed = 'closed', _("Closed")
 | 
					    closed = 'closed', _("Closed")
 | 
				
			||||||
    reopen = 'reopen', _("Reopen")
 | 
					 | 
				
			||||||
    approved = 'approved', _('Approved')
 | 
					    approved = 'approved', _('Approved')
 | 
				
			||||||
    rejected = 'rejected', _('Rejected')
 | 
					    rejected = 'rejected', _('Rejected')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
from django.db.models import Subquery, OuterRef,  Value, F, Q
 | 
					from django.db.models import Subquery, OuterRef, Value, F, Q
 | 
				
			||||||
from django_filters import rest_framework as filters
 | 
					from django_filters import rest_framework as filters
 | 
				
			||||||
from django.db.models.functions import Concat
 | 
					from django.db.models.functions import Concat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,10 +11,9 @@ from tickets.models import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TicketFilter(BaseFilterSet):
 | 
					class TicketFilter(BaseFilterSet):
 | 
				
			||||||
 | 
					    applicant = filters.CharFilter(method='filter_applicant')
 | 
				
			||||||
    assignees__id = filters.UUIDFilter(method='filter_assignees_id')
 | 
					    assignees__id = filters.UUIDFilter(method='filter_assignees_id')
 | 
				
			||||||
    relevant_app = filters.CharFilter(method='filter_relevant_app')
 | 
					 | 
				
			||||||
    relevant_asset = filters.CharFilter(method='filter_relevant_asset')
 | 
					    relevant_asset = filters.CharFilter(method='filter_relevant_asset')
 | 
				
			||||||
    relevant_system_user = filters.CharFilter(method='filter_relevant_system_user')
 | 
					 | 
				
			||||||
    relevant_command = filters.CharFilter(method='filter_relevant_command')
 | 
					    relevant_command = filters.CharFilter(method='filter_relevant_command')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
| 
						 | 
					@ -64,6 +63,11 @@ class TicketFilter(BaseFilterSet):
 | 
				
			||||||
        ).values_list('id', flat=True)
 | 
					        ).values_list('id', flat=True)
 | 
				
			||||||
        return queryset.filter(id__in=list(command_ids))
 | 
					        return queryset.filter(id__in=list(command_ids))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def filter_applicant(self, queryset, name, value):
 | 
				
			||||||
 | 
					        return queryset.filter(
 | 
				
			||||||
 | 
					            Q(applicant__username__icontains=value) | Q(applicant__name__icontains=value)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApplyAssetTicketFilter(BaseFilterSet):
 | 
					class ApplyAssetTicketFilter(BaseFilterSet):
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ class BaseHandler:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _create_state_change_comment(self, state):
 | 
					    def _create_state_change_comment(self, state):
 | 
				
			||||||
        # 打开或关闭工单,备注显示是自己,其他是受理人
 | 
					        # 打开或关闭工单,备注显示是自己,其他是受理人
 | 
				
			||||||
        if state in [TicketState.reopen, TicketState.pending, TicketState.closed]:
 | 
					        if state in [TicketState.pending, TicketState.closed]:
 | 
				
			||||||
            user = self.ticket.applicant
 | 
					            user = self.ticket.applicant
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            user = self.ticket.processor
 | 
					            user = self.ticket.processor
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ class Migration(migrations.Migration):
 | 
				
			||||||
            model_name='ticket',
 | 
					            model_name='ticket',
 | 
				
			||||||
            name='state',
 | 
					            name='state',
 | 
				
			||||||
            field=models.CharField(choices=[('pending', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'),
 | 
					            field=models.CharField(choices=[('pending', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'),
 | 
				
			||||||
                                            ('closed', 'Cancel'), ('reopen', 'Reopen')], default='pending',
 | 
					                                            ('closed', 'Cancel')], default='pending',
 | 
				
			||||||
                                   max_length=16, verbose_name='State'),
 | 
					                                   max_length=16, verbose_name='State'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
| 
						 | 
					@ -74,14 +74,14 @@ class Migration(migrations.Migration):
 | 
				
			||||||
            model_name='ticketassignee',
 | 
					            model_name='ticketassignee',
 | 
				
			||||||
            name='state',
 | 
					            name='state',
 | 
				
			||||||
            field=models.CharField(choices=[('pending', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'),
 | 
					            field=models.CharField(choices=[('pending', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'),
 | 
				
			||||||
                                            ('closed', 'Cancel'), ('reopen', 'Reopen')], default='pending',
 | 
					                                            ('closed', 'Cancel')], default='pending',
 | 
				
			||||||
                                   max_length=64),
 | 
					                                   max_length=64),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='ticketstep',
 | 
					            model_name='ticketstep',
 | 
				
			||||||
            name='state',
 | 
					            name='state',
 | 
				
			||||||
            field=models.CharField(choices=[('pending', 'Pending'), ('approved', 'Approved'), ('rejected', 'Rejected'),
 | 
					            field=models.CharField(choices=[('pending', 'Pending'), ('approved', 'Approved'), ('rejected', 'Rejected'),
 | 
				
			||||||
                                            ('closed', 'Closed'), ('reopen', 'Reopen')], default='pending',
 | 
					                                            ('closed', 'Closed')], default='pending',
 | 
				
			||||||
                                   max_length=64, verbose_name='State'),
 | 
					                                   max_length=64, verbose_name='State'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.CreateModel(
 | 
					        migrations.CreateModel(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,8 +30,7 @@ class Migration(migrations.Migration):
 | 
				
			||||||
            field=models.CharField(
 | 
					            field=models.CharField(
 | 
				
			||||||
                choices=[
 | 
					                choices=[
 | 
				
			||||||
                    ('pending', 'Open'), ('closed', 'Cancel'),
 | 
					                    ('pending', 'Open'), ('closed', 'Cancel'),
 | 
				
			||||||
                    ('reopen', 'Reopen'), ('approved', 'Approved'),
 | 
					                    ('approved', 'Approved'), ('rejected', 'Rejected')
 | 
				
			||||||
                    ('rejected', 'Rejected')
 | 
					 | 
				
			||||||
                ], default='pending', max_length=16, verbose_name='State'),
 | 
					                ], default='pending', max_length=16, verbose_name='State'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
| 
						 | 
					@ -51,8 +50,7 @@ class Migration(migrations.Migration):
 | 
				
			||||||
            field=models.CharField(
 | 
					            field=models.CharField(
 | 
				
			||||||
                choices=[
 | 
					                choices=[
 | 
				
			||||||
                    ('pending', 'Open'), ('closed', 'Cancel'),
 | 
					                    ('pending', 'Open'), ('closed', 'Cancel'),
 | 
				
			||||||
                    ('reopen', 'Reopen'), ('approved', 'Approved'),
 | 
					                    ('approved', 'Approved'), ('rejected', 'Rejected')
 | 
				
			||||||
                    ('rejected', 'Rejected')
 | 
					 | 
				
			||||||
                ], default='pending', max_length=64),
 | 
					                ], default='pending', max_length=64),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
| 
						 | 
					@ -72,8 +70,7 @@ class Migration(migrations.Migration):
 | 
				
			||||||
            field=models.CharField(
 | 
					            field=models.CharField(
 | 
				
			||||||
                choices=[
 | 
					                choices=[
 | 
				
			||||||
                    ('pending', 'Pending'), ('closed', 'Closed'),
 | 
					                    ('pending', 'Pending'), ('closed', 'Closed'),
 | 
				
			||||||
                    ('reopen', 'Reopen'), ('approved', 'Approved'),
 | 
					                    ('approved', 'Approved'), ('rejected', 'Rejected')
 | 
				
			||||||
                    ('rejected', 'Rejected')
 | 
					 | 
				
			||||||
                ], default='pending', max_length=64, verbose_name='State'),
 | 
					                ], default='pending', max_length=64, verbose_name='State'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,6 @@ from django.db import migrations, models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Migration(migrations.Migration):
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					 | 
				
			||||||
    dependencies = [
 | 
					    dependencies = [
 | 
				
			||||||
        ('tickets', '0023_alter_applyassetticket_apply_actions'),
 | 
					        ('tickets', '0023_alter_applyassetticket_apply_actions'),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
| 
						 | 
					@ -13,36 +12,52 @@ class Migration(migrations.Migration):
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='approvalrule',
 | 
					            model_name='approvalrule',
 | 
				
			||||||
            name='strategy',
 | 
					            name='strategy',
 | 
				
			||||||
            field=models.CharField(choices=[('org_admin', 'Org admin'), ('custom_user', 'Custom user'), ('super_admin', 'Super admin'), ('super_org_admin', 'Super admin and org admin')], default='super_admin', max_length=64, verbose_name='Approve strategy'),
 | 
					            field=models.CharField(
 | 
				
			||||||
 | 
					                choices=[('org_admin', 'Org admin'), ('custom_user', 'Custom user'), ('super_admin', 'Super admin'),
 | 
				
			||||||
 | 
					                         ('super_org_admin', 'Super admin and org admin')], default='super_admin', max_length=64,
 | 
				
			||||||
 | 
					                verbose_name='Approve strategy'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='ticket',
 | 
					            model_name='ticket',
 | 
				
			||||||
            name='state',
 | 
					            name='state',
 | 
				
			||||||
            field=models.CharField(choices=[('pending', 'Open'), ('closed', 'Cancel'), ('reopen', 'Reopen'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=16, verbose_name='State'),
 | 
					            field=models.CharField(
 | 
				
			||||||
 | 
					                choices=[('pending', 'Open'), ('closed', 'Cancel'), ('approved', 'Approved'), ('rejected', 'Rejected')],
 | 
				
			||||||
 | 
					                default='pending', max_length=16, verbose_name='State'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='ticket',
 | 
					            model_name='ticket',
 | 
				
			||||||
            name='type',
 | 
					            name='type',
 | 
				
			||||||
            field=models.CharField(choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'), ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')], default='general', max_length=64, verbose_name='Type'),
 | 
					            field=models.CharField(
 | 
				
			||||||
 | 
					                choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'),
 | 
				
			||||||
 | 
					                         ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')],
 | 
				
			||||||
 | 
					                default='general', max_length=64, verbose_name='Type'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='ticketassignee',
 | 
					            model_name='ticketassignee',
 | 
				
			||||||
            name='state',
 | 
					            name='state',
 | 
				
			||||||
            field=models.CharField(choices=[('pending', 'Open'), ('closed', 'Cancel'), ('reopen', 'Reopen'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=64),
 | 
					            field=models.CharField(
 | 
				
			||||||
 | 
					                choices=[('pending', 'Open'), ('closed', 'Cancel'), ('approved', 'Approved'), ('rejected', 'Rejected')],
 | 
				
			||||||
 | 
					                default='pending', max_length=64),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='ticketflow',
 | 
					            model_name='ticketflow',
 | 
				
			||||||
            name='type',
 | 
					            name='type',
 | 
				
			||||||
            field=models.CharField(choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'), ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')], default='general', max_length=64, verbose_name='Type'),
 | 
					            field=models.CharField(
 | 
				
			||||||
 | 
					                choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'),
 | 
				
			||||||
 | 
					                         ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')],
 | 
				
			||||||
 | 
					                default='general', max_length=64, verbose_name='Type'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='ticketstep',
 | 
					            model_name='ticketstep',
 | 
				
			||||||
            name='state',
 | 
					            name='state',
 | 
				
			||||||
            field=models.CharField(choices=[('pending', 'Pending'), ('closed', 'Closed'), ('reopen', 'Reopen'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=64, verbose_name='State'),
 | 
					            field=models.CharField(choices=[('pending', 'Pending'), ('closed', 'Closed'), ('approved', 'Approved'),
 | 
				
			||||||
 | 
					                                            ('rejected', 'Rejected')], default='pending', max_length=64,
 | 
				
			||||||
 | 
					                                   verbose_name='State'),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.AlterField(
 | 
					        migrations.AlterField(
 | 
				
			||||||
            model_name='ticketstep',
 | 
					            model_name='ticketstep',
 | 
				
			||||||
            name='status',
 | 
					            name='status',
 | 
				
			||||||
            field=models.CharField(choices=[('active', 'Active'), ('closed', 'Closed'), ('pending', 'Pending')], default='pending', max_length=16),
 | 
					            field=models.CharField(choices=[('active', 'Active'), ('closed', 'Closed'), ('pending', 'Pending')],
 | 
				
			||||||
 | 
					                                   default='pending', max_length=16),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,16 +143,13 @@ class StatusMixin:
 | 
				
			||||||
    def reject(self, processor):
 | 
					    def reject(self, processor):
 | 
				
			||||||
        self._change_state(StepState.rejected, processor)
 | 
					        self._change_state(StepState.rejected, processor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reopen(self):
 | 
					 | 
				
			||||||
        self._change_state_by_applicant(TicketState.reopen)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def close(self):
 | 
					    def close(self):
 | 
				
			||||||
        self._change_state(TicketState.closed, self.applicant)
 | 
					        self._change_state(TicketState.closed, self.applicant)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _change_state_by_applicant(self, state):
 | 
					    def _change_state_by_applicant(self, state):
 | 
				
			||||||
        if state == TicketState.closed:
 | 
					        if state == TicketState.closed:
 | 
				
			||||||
            self.status = TicketStatus.closed
 | 
					            self.status = TicketStatus.closed
 | 
				
			||||||
        elif state in [TicketState.reopen, TicketState.pending]:
 | 
					        elif state == TicketState.pending:
 | 
				
			||||||
            self.status = TicketStatus.open
 | 
					            self.status = TicketStatus.open
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            raise ValueError("Not supported state: {}".format(state))
 | 
					            raise ValueError("Not supported state: {}".format(state))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ __all__ = [
 | 
				
			||||||
class TicketSerializer(OrgResourceModelSerializerMixin):
 | 
					class TicketSerializer(OrgResourceModelSerializerMixin):
 | 
				
			||||||
    type = LabeledChoiceField(choices=TicketType.choices, read_only=True, label=_('Type'))
 | 
					    type = LabeledChoiceField(choices=TicketType.choices, read_only=True, label=_('Type'))
 | 
				
			||||||
    status = LabeledChoiceField(choices=TicketStatus.choices, read_only=True, label=_('Status'))
 | 
					    status = LabeledChoiceField(choices=TicketStatus.choices, read_only=True, label=_('Status'))
 | 
				
			||||||
    state = LabeledChoiceField(choices=TicketState.choices, read_only=True, label=_("State"))
 | 
					    state = LabeledChoiceField(choices=TicketState.choices, read_only=True, label=_("Action"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = Ticket
 | 
					        model = Ticket
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue