fix: unify workflow action permissions

This commit is contained in:
caoqianming 2026-07-27 13:20:58 +08:00
parent 919ac890a9
commit c3f2c0f136
2 changed files with 87 additions and 2 deletions

View File

@ -1,3 +1,60 @@
from django.test import TestCase from types import SimpleNamespace
from unittest.mock import MagicMock, patch
# Create your tests here. from django.test import SimpleTestCase
from rest_framework.test import APIRequestFactory
from apps.wf.views import TicketViewSet
class TicketAvailableActionsTests(SimpleTestCase):
def setUp(self):
self.request = APIRequestFactory().get('/api/wf/ticket/1/available_actions/')
self.request.user = SimpleNamespace(id='user-1')
self.view = TicketViewSet()
self.ticket = SimpleNamespace(in_add_node=False)
self.view.get_object = MagicMock(return_value=self.ticket)
@patch('apps.wf.views.TransitionSerializer')
@patch('apps.wf.views.WfService.get_ticket_transitions')
@patch('apps.wf.views.WfService.ticket_handle_permission_check')
def test_returns_transitions_when_user_can_handle(
self, permission_check, get_transitions, serializer):
permission_check.return_value = {
'permission': True,
'need_accept': False,
'msg': '',
}
transitions = MagicMock()
transitions.select_related.return_value = transitions
get_transitions.return_value = transitions
serializer.return_value.data = [{'id': 'transition-1', 'name': '同意'}]
response = self.view.available_actions(self.request)
self.assertTrue(response.data['permission'])
self.assertFalse(response.data['need_accept'])
self.assertEqual(
response.data['transitions'],
[{'id': 'transition-1', 'name': '同意'}],
)
@patch('apps.wf.views.TransitionSerializer')
@patch('apps.wf.views.WfService.get_ticket_transitions')
@patch('apps.wf.views.WfService.ticket_handle_permission_check')
def test_hides_transitions_and_requests_accept_for_active_distribution(
self, permission_check, get_transitions, serializer):
permission_check.return_value = {
'permission': False,
'need_accept': True,
'msg': '需要先接单再处理',
}
response = self.view.available_actions(self.request)
self.assertFalse(response.data['permission'])
self.assertTrue(response.data['need_accept'])
self.assertEqual(response.data['message'], '需要先接单再处理')
self.assertEqual(response.data['transitions'], [])
get_transitions.assert_not_called()
serializer.assert_not_called()

View File

@ -363,6 +363,34 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R
transitions = WfService.get_ticket_transitions(ticket) transitions = WfService.get_ticket_transitions(ticket)
return Response(TransitionSerializer(instance=transitions.select_related('source_state', 'destination_state'), many=True).data) return Response(TransitionSerializer(instance=transitions.select_related('source_state', 'destination_state'), many=True).data)
@action(methods=['get'], detail=True, perms_map={'get': '*'})
def available_actions(self, request, pk=None):
"""
获取当前用户对工单可执行的操作及接单状态
前端应使用该接口决定是否展示处理按钮避免自行解释 participant
后与后端实际处理权限不一致 transitions 接口保留用于兼容
"""
ticket = self.get_object()
permission_result = WfService.ticket_handle_permission_check(
ticket, request.user
)
transitions = []
if permission_result.get('permission', False):
transition_queryset = WfService.get_ticket_transitions(
ticket
).select_related('source_state', 'destination_state')
transitions = TransitionSerializer(
instance=transition_queryset, many=True
).data
return Response({
'permission': permission_result.get('permission', False),
'need_accept': permission_result.get('need_accept', False),
'message': permission_result.get('msg', ''),
'in_add_node': ticket.in_add_node,
'transitions': transitions,
})
@action(methods=['post'], detail=True, perms_map={'post': '*'}) @action(methods=['post'], detail=True, perms_map={'post': '*'})
def accpet(self, request, pk=None): def accpet(self, request, pk=None):
""" """