feat: 工单多级审批 + 模版创建 (#6640)

* feat: 工单多级审批 + 模版创建

* feat: 工单权限处理

* fix: 工单关闭后 再审批bug

* perf: 修改一点

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: ibuler <ibuler@qq.com>
This commit is contained in:
fit2bot
2021-08-25 19:02:50 +08:00
committed by GitHub
parent 1fdc558ef7
commit 0f87f05b3f
30 changed files with 897 additions and 590 deletions

View File

@@ -1,17 +1,19 @@
from django.utils.translation import ugettext as _
from orgs.utils import tmp_to_org, tmp_to_root_org
from applications.models import Application
from applications.const import AppCategory, AppType
from assets.models import SystemUser
from applications.models import Application
from perms.models import ApplicationPermission
from assets.models import SystemUser
from .base import BaseHandler
class Handler(BaseHandler):
def _on_approve(self):
super()._on_approve()
self._create_application_permission()
is_finished = super()._on_approve()
if is_finished:
self._create_application_permission()
# display
def _construct_meta_display_of_open(self):
@@ -22,27 +24,21 @@ class Handler(BaseHandler):
apply_type_display = AppType.get_label(apply_type)
meta_display_values = [apply_category_display, apply_type_display]
meta_display = dict(zip(meta_display_fields, meta_display_values))
return meta_display
apply_system_users = self.ticket.meta.get('apply_system_users')
apply_applications = self.ticket.meta.get('apply_applications')
meta_display.update({
'apply_system_users_display': [str(i) for i in SystemUser.objects.filter(id__in=apply_system_users)],
'apply_applications_display': [str(i) for i in Application.objects.filter(id__in=apply_applications)]
})
def _construct_meta_display_of_approve(self):
meta_display_fields = ['approve_applications_display', 'approve_system_users_display']
approve_application_ids = self.ticket.meta.get('approve_applications', [])
approve_system_user_ids = self.ticket.meta.get('approve_system_users', [])
with tmp_to_org(self.ticket.org_id):
approve_applications = Application.objects.filter(id__in=approve_application_ids)
system_users = SystemUser.objects.filter(id__in=approve_system_user_ids)
approve_applications_display = [str(application) for application in approve_applications]
approve_system_users_display = [str(system_user) for system_user in system_users]
meta_display_values = [approve_applications_display, approve_system_users_display]
meta_display = dict(zip(meta_display_fields, meta_display_values))
return meta_display
# body
def _construct_meta_body_of_open(self):
apply_category_display = self.ticket.meta.get('apply_category_display')
apply_type_display = self.ticket.meta.get('apply_type_display')
apply_application_group = self.ticket.meta.get('apply_application_group', [])
apply_system_user_group = self.ticket.meta.get('apply_system_user_group', [])
apply_applications = self.ticket.meta.get('apply_applications', [])
apply_system_users = self.ticket.meta.get('apply_system_users', [])
apply_date_start = self.ticket.meta.get('apply_date_start')
apply_date_expired = self.ticket.meta.get('apply_date_expired')
applied_body = '''{}: {},
@@ -54,31 +50,13 @@ class Handler(BaseHandler):
'''.format(
_('Applied category'), apply_category_display,
_('Applied type'), apply_type_display,
_('Applied application group'), apply_application_group,
_('Applied system user group'), apply_system_user_group,
_('Applied application group'), apply_applications,
_('Applied system user group'), apply_system_users,
_('Applied date start'), apply_date_start,
_('Applied date expired'), apply_date_expired,
)
return applied_body
def _construct_meta_body_of_approve(self):
# 审批信息
approve_applications_display = self.ticket.meta.get('approve_applications_display', [])
approve_system_users_display = self.ticket.meta.get('approve_system_users_display', [])
approve_date_start = self.ticket.meta.get('approve_date_start')
approve_date_expired = self.ticket.meta.get('approve_date_expired')
approved_body = '''{}: {},
{}: {},
{}: {},
{}: {},
'''.format(
_('Approved applications'), approve_applications_display,
_('Approved system users'), approve_system_users_display,
_('Approved date start'), approve_date_start,
_('Approved date expired'), approve_date_expired
)
return approved_body
# permission
def _create_application_permission(self):
with tmp_to_root_org():
@@ -88,11 +66,11 @@ class Handler(BaseHandler):
apply_category = self.ticket.meta.get('apply_category')
apply_type = self.ticket.meta.get('apply_type')
approve_permission_name = self.ticket.meta.get('approve_permission_name', '')
approved_application_ids = self.ticket.meta.get('approve_applications', [])
approve_system_user_ids = self.ticket.meta.get('approve_system_users', [])
approve_date_start = self.ticket.meta.get('approve_date_start')
approve_date_expired = self.ticket.meta.get('approve_date_expired')
apply_permission_name = self.ticket.meta.get('apply_permission_name', '')
apply_applications = self.ticket.meta.get('apply_applications', [])
apply_system_users = self.ticket.meta.get('apply_system_users', [])
apply_date_start = self.ticket.meta.get('apply_date_start')
apply_date_expired = self.ticket.meta.get('apply_date_expired')
permission_created_by = '{}:{}'.format(
str(self.ticket.__class__.__name__), str(self.ticket.id)
)
@@ -105,23 +83,23 @@ class Handler(BaseHandler):
).format(
self.ticket.title,
self.ticket.applicant_display,
self.ticket.processor_display,
str(self.ticket.processor),
str(self.ticket.id)
)
permissions_data = {
'id': self.ticket.id,
'name': approve_permission_name,
'name': apply_permission_name,
'category': apply_category,
'type': apply_type,
'comment': str(permission_comment),
'created_by': permission_created_by,
'date_start': approve_date_start,
'date_expired': approve_date_expired,
'date_start': apply_date_start,
'date_expired': apply_date_expired,
}
with tmp_to_org(self.ticket.org_id):
application_permission = ApplicationPermission.objects.create(**permissions_data)
application_permission.users.add(self.ticket.applicant)
application_permission.applications.set(approved_application_ids)
application_permission.system_users.set(approve_system_user_ids)
application_permission.applications.set(apply_applications)
application_permission.system_users.set(apply_system_users)
return application_permission

View File

@@ -1,16 +1,19 @@
from assets.models import Asset
from assets.models import SystemUser
from .base import BaseHandler
from django.utils.translation import ugettext as _
from perms.models import AssetPermission, Action
from assets.models import Asset, SystemUser
from orgs.utils import tmp_to_org, tmp_to_root_org
class Handler(BaseHandler):
def _on_approve(self):
super()._on_approve()
self._create_asset_permission()
is_finished = super()._on_approve()
if is_finished:
self._create_asset_permission()
# display
def _construct_meta_display_of_open(self):
@@ -19,32 +22,18 @@ class Handler(BaseHandler):
apply_actions_display = Action.value_to_choices_display(apply_actions)
meta_display_values = [apply_actions_display]
meta_display = dict(zip(meta_display_fields, meta_display_values))
return meta_display
def _construct_meta_display_of_approve(self):
meta_display_fields = [
'approve_actions_display', 'approve_assets_display', 'approve_system_users_display'
]
approve_actions = self.ticket.meta.get('approve_actions', Action.NONE)
approve_actions_display = Action.value_to_choices_display(approve_actions)
approve_asset_ids = self.ticket.meta.get('approve_assets', [])
approve_system_user_ids = self.ticket.meta.get('approve_system_users', [])
with tmp_to_org(self.ticket.org_id):
assets = Asset.objects.filter(id__in=approve_asset_ids)
system_users = SystemUser.objects.filter(id__in=approve_system_user_ids)
approve_assets_display = [str(asset) for asset in assets]
approve_system_users_display = [str(system_user) for system_user in system_users]
meta_display_values = [
approve_actions_display, approve_assets_display, approve_system_users_display
]
meta_display = dict(zip(meta_display_fields, meta_display_values))
apply_assets = self.ticket.meta.get('apply_assets')
apply_system_users = self.ticket.meta.get('apply_system_users')
meta_display.update({
'apply_assets_display': [str(i) for i in Asset.objects.filter(id__in=apply_assets)],
'apply_system_users_display': [str(i)for i in SystemUser.objects.filter(id__in=apply_system_users)]
})
return meta_display
# body
def _construct_meta_body_of_open(self):
apply_ip_group = self.ticket.meta.get('apply_ip_group', [])
apply_hostname_group = self.ticket.meta.get('apply_hostname_group', [])
apply_system_user_group = self.ticket.meta.get('apply_system_user_group', [])
apply_assets = self.ticket.meta.get('apply_assets', [])
apply_system_users = self.ticket.meta.get('apply_system_users', [])
apply_actions_display = self.ticket.meta.get('apply_actions_display', [])
apply_date_start = self.ticket.meta.get('apply_date_start')
apply_date_expired = self.ticket.meta.get('apply_date_expired')
@@ -54,35 +43,14 @@ class Handler(BaseHandler):
{}: {},
{}: {}
'''.format(
_('Applied IP group'), apply_ip_group,
_("Applied hostname group"), apply_hostname_group,
_("Applied system user group"), apply_system_user_group,
_("Applied hostname group"), apply_assets,
_("Applied system user group"), apply_system_users,
_("Applied actions"), apply_actions_display,
_('Applied date start'), apply_date_start,
_('Applied date expired'), apply_date_expired,
)
return applied_body
def _construct_meta_body_of_approve(self):
approve_assets_display = self.ticket.meta.get('approve_assets_display', [])
approve_system_users_display = self.ticket.meta.get('approve_system_users_display', [])
approve_actions_display = self.ticket.meta.get('approve_actions_display', [])
approve_date_start = self.ticket.meta.get('approve_date_start')
approve_date_expired = self.ticket.meta.get('approve_date_expired')
approved_body = '''{}: {},
{}: {},
{}: {},
{}: {},
{}: {}
'''.format(
_('Approved assets'), approve_assets_display,
_('Approved system users'), approve_system_users_display,
_('Approved actions'), ', '.join(approve_actions_display),
_('Approved date start'), approve_date_start,
_('Approved date expired'), approve_date_expired,
)
return approved_body
# permission
def _create_asset_permission(self):
with tmp_to_root_org():
@@ -90,12 +58,12 @@ class Handler(BaseHandler):
if asset_permission:
return asset_permission
approve_permission_name = self.ticket.meta.get('approve_permission_name', )
approve_asset_ids = self.ticket.meta.get('approve_assets', [])
approve_system_user_ids = self.ticket.meta.get('approve_system_users', [])
approve_actions = self.ticket.meta.get('approve_actions', Action.NONE)
approve_date_start = self.ticket.meta.get('approve_date_start')
approve_date_expired = self.ticket.meta.get('approve_date_expired')
apply_permission_name = self.ticket.meta.get('apply_permission_name', )
apply_assets = self.ticket.meta.get('apply_assets', [])
apply_system_users = self.ticket.meta.get('apply_system_users', [])
apply_actions = self.ticket.meta.get('apply_actions', Action.NONE)
apply_date_start = self.ticket.meta.get('apply_date_start')
apply_date_expired = self.ticket.meta.get('apply_date_expired')
permission_created_by = '{}:{}'.format(
str(self.ticket.__class__.__name__), str(self.ticket.id)
)
@@ -108,23 +76,23 @@ class Handler(BaseHandler):
).format(
self.ticket.title,
self.ticket.applicant_display,
self.ticket.processor_display,
str(self.ticket.processor),
str(self.ticket.id)
)
permission_data = {
'id': self.ticket.id,
'name': approve_permission_name,
'name': apply_permission_name,
'comment': str(permission_comment),
'created_by': permission_created_by,
'actions': approve_actions,
'date_start': approve_date_start,
'date_expired': approve_date_expired,
'actions': apply_actions,
'date_start': apply_date_start,
'date_expired': apply_date_expired,
}
with tmp_to_org(self.ticket.org_id):
asset_permission = AssetPermission.objects.create(**permission_data)
asset_permission.users.add(self.ticket.applicant)
asset_permission.assets.set(approve_asset_ids)
asset_permission.system_users.set(approve_system_user_ids)
asset_permission.assets.set(apply_assets)
asset_permission.system_users.set(apply_system_users)
return asset_permission

View File

@@ -3,7 +3,7 @@ from common.utils import get_logger
from tickets.utils import (
send_ticket_processed_mail_to_applicant, send_ticket_applied_mail_to_assignees
)
from tickets.const import TicketAction
logger = get_logger(__name__)
@@ -16,48 +16,72 @@ class BaseHandler(object):
# on action
def _on_open(self):
self.ticket.applicant_display = str(self.ticket.applicant)
self.ticket.assignees_display = [str(assignee) for assignee in self.ticket.assignees.all()]
meta_display = getattr(self, '_construct_meta_display_of_open', lambda: {})()
self.ticket.meta.update(meta_display)
self.ticket.save()
self._send_applied_mail_to_assignees()
def _on_approve(self):
meta_display = getattr(self, '_construct_meta_display_of_approve', lambda: {})()
self.ticket.meta.update(meta_display)
self.__on_process()
if self.ticket.approval_step != len(self.ticket.process_map):
self.ticket.approval_step += 1
self.ticket.create_related_node()
is_finished = False
else:
self.ticket.set_state_approve()
self.ticket.set_status_closed()
is_finished = True
self._send_applied_mail_to_assignees()
self.__on_process(self.ticket.processor)
return is_finished
def _on_reject(self):
self.__on_process()
self.ticket.set_state_reject()
self.ticket.set_status_closed()
self.__on_process(self.ticket.processor)
def _on_close(self):
self.__on_process()
def __on_process(self):
self.ticket.processor_display = str(self.ticket.processor)
self.ticket.set_state_closed()
self.ticket.set_status_closed()
self._send_processed_mail_to_applicant()
self.__on_process(self.ticket.processor)
def __on_process(self, processor):
self._send_processed_mail_to_applicant(processor)
self.ticket.save()
def dispatch(self, action):
self._create_comment_on_action()
processor = self.ticket.processor
current_node = self.ticket.current_node.first()
self.ticket.process_map[self.ticket.approval_step - 1].update({
'approval_date': str(current_node.date_updated),
'state': current_node.state,
'processor': processor.id if processor else '',
'processor_display': str(processor) if processor else '',
})
self.ticket.save()
self._create_comment_on_action(action)
method = getattr(self, f'_on_{action}', lambda: None)
return method()
# email
def _send_applied_mail_to_assignees(self):
logger.debug('Send applied email to assignees: {}'.format(self.ticket.assignees_display))
assignees = self.ticket.current_node.first().ticket_assignees.all()
assignees_display = ', '.join([str(i.assignee) for i in assignees])
logger.debug('Send applied email to assignees: {}'.format(assignees_display))
send_ticket_applied_mail_to_assignees(self.ticket)
def _send_processed_mail_to_applicant(self):
def _send_processed_mail_to_applicant(self, processor):
logger.debug('Send processed mail to applicant: {}'.format(self.ticket.applicant_display))
send_ticket_processed_mail_to_applicant(self.ticket)
send_ticket_processed_mail_to_applicant(self.ticket, processor)
# comments
def _create_comment_on_action(self):
user = self.ticket.applicant if self.ticket.action_open else self.ticket.processor
def _create_comment_on_action(self, action):
user = self.ticket.processor
# 打开或关闭工单,备注显示是自己,其他是受理人
if self.ticket.state_open or self.ticket.state_close:
user = self.ticket.applicant
user_display = str(user)
action_display = self.ticket.get_action_display()
action_display = getattr(TicketAction, action).label
data = {
'body': _('{} {} the ticket').format(user_display, action_display),
'user': user,
@@ -85,18 +109,12 @@ class BaseHandler(object):
{}: {},
{}: {},
{}: {},
{}: {},
{}: {}
'''.format(
_('Ticket title'), self.ticket.title,
_('Ticket type'), self.ticket.get_type_display(),
_('Ticket status'), self.ticket.get_status_display(),
_('Ticket action'), self.ticket.get_action_display(),
_('Ticket applicant'), self.ticket.applicant_display,
_('Ticket assignees'), ', '.join(self.ticket.assignees_display),
)
if self.ticket.status_closed:
basic_body += '''{}: {}'''.format(_('Ticket processor'), self.ticket.processor_display)
body = self.body_html_format.format(_("Ticket basic info"), basic_body)
return body
@@ -104,9 +122,6 @@ class BaseHandler(object):
body = ''
open_body = self._base_construct_meta_body_of_open()
body += open_body
if self.ticket.action_approve:
approve_body = self._base_construct_meta_body_of_approve()
body += approve_body
return body
def _base_construct_meta_body_of_open(self):
@@ -115,10 +130,3 @@ class BaseHandler(object):
)()
body = self.body_html_format.format(_('Ticket applied info'), meta_body_of_open)
return body
def _base_construct_meta_body_of_approve(self):
meta_body_of_approve = getattr(
self, '_construct_meta_body_of_approve', lambda: _('No content')
)()
body = self.body_html_format.format(_('Ticket approved info'), meta_body_of_approve)
return body