123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689 |
- import json
- from django.http import HttpResponse
- from django.views import View
- from schema import Schema, Regex, And, Or, Use, Optional
- from apps.loon_base_view import LoonBaseView
- from service.account.account_base_service import account_base_service_ins
- from service.format_response import api_response
- from service.ticket.ticket_base_service import ticket_base_service_ins
- class TicketListView(LoonBaseView):
- post_schema = Schema({
- 'workflow_id': And(int, lambda n: n != 0, error='workflow_id is needed and type should be int'),
- 'transition_id': And(int, lambda n: n != 0, error='transition_id is needed and type should be int'),
- str: object
- })
- def get(self, request, *args, **kwargs):
- """
- 获取工单列表
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- request_data = request.GET
- sn = request_data.get('sn', '')
- title = request_data.get('title', '')
- # username = request_data.get('username', '')
- username = request.META.get('HTTP_USERNAME')
- create_start = request_data.get('create_start', '')
- create_end = request_data.get('create_end', '')
- workflow_ids = request_data.get('workflow_ids', '')
- state_ids = request_data.get('state_ids', '')
- ticket_ids = request_data.get('ticket_ids', '')
- reverse = int(request_data.get('reverse', 1))
- per_page = int(request_data.get('per_page', 10))
- page = int(request_data.get('page', 1))
- act_state_id = request_data.get('act_state_id', '')
- from_admin = request_data.get('from_admin', '')
- creator = request_data.get('creator', '')
- parent_ticket_id = int(request_data.get('parent_ticket_id', 0))
- parent_ticket_state_id = int(request_data.get('parent_ticket_state_id', 0))
- # 待办,关联的,创建
- category = request_data.get('category')
- # app_name
- app_name = request.META.get('HTTP_APPNAME')
- # 未指定创建起止时间则取最近三年的记录
- if not(create_start or create_end):
- import datetime
- end_time = datetime.datetime.now() + datetime.timedelta(hours=1)
- last_year_time = datetime.datetime.now() - datetime.timedelta(days=365*3)
- create_start = str(last_year_time)[:19]
- create_end = str(end_time)[:19]
- flag, result = ticket_base_service_ins.get_ticket_list(
- sn=sn, title=title, username=username, create_start=create_start, create_end=create_end,
- workflow_ids=workflow_ids, state_ids=state_ids, ticket_ids=ticket_ids, category=category, reverse=reverse,
- per_page=per_page, page=page, app_name=app_name, act_state_id=act_state_id, from_admin=from_admin,
- creator=creator, parent_ticket_id=parent_ticket_id, parent_ticket_state_id=parent_ticket_state_id)
- if flag is not False:
- paginator_info = result.get('paginator_info')
- data = dict(value=result.get('ticket_result_restful_list'), per_page=paginator_info.get('per_page'),
- page=paginator_info.get('page'), total=paginator_info.get('total'))
- code, msg, = 0, ''
- else:
- code, data, msg = -1, {}, result
- return api_response(code, msg, data)
- def post(self, request, *args, **kwargs):
- """
- 新建工单,需要根据不同类型工单传的参数不一样
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- request_data_dict = json.loads(json_str)
- app_name = request.META.get('HTTP_APPNAME')
- request_data_dict.update(dict(username=request.META.get('HTTP_USERNAME')))
- # 判断是否有创建某工单的权限
- app_permission, msg = account_base_service_ins.app_workflow_permission_check(app_name, request_data_dict.get('workflow_id'))
- if not app_permission:
- return api_response(-1, 'APP:{} have no permission to create this workflow ticket'.format(app_name), '')
- flag, result = ticket_base_service_ins.new_ticket(request_data_dict, app_name)
- if flag:
- code, data = 0, {'ticket_id': result.get('new_ticket_id')}
- else:
- code, data = -1, {}
- return api_response(code, result, data)
- class TicketView(LoonBaseView):
- def get(self, request, *args, **kwargs):
- """
- 获取工单详情,根据用户返回不同的内容(是否有工单表单的编辑权限)
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- request_data = request.GET
- ticket_id = kwargs.get('ticket_id')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- # username = request_data.get('username', '')
- username = request.META.get('HTTP_USERNAME')
- if not username:
- return api_response(-1, '参数不全,请提供username', '')
- flag, result = ticket_base_service_ins.get_ticket_detail(ticket_id, username)
- if flag:
- code, data = 0, dict(value=result)
- else:
- code, data, msg = -1, {}, result
- return api_response(code, msg, data)
- def patch(self, request, *args, **kwargs):
- """
- 处理工单
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- if not json_str:
- return api_response(-1, 'patch参数为空', {})
- request_data_dict = json.loads(json_str)
- ticket_id = kwargs.get('ticket_id')
- app_name = request.META.get('HTTP_APPNAME')
- request_data_dict.update(dict(username=request.META.get('HTTP_USERNAME')))
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, {})
- result, msg = ticket_base_service_ins.handle_ticket(ticket_id, request_data_dict)
- if result or result is not False:
- code, data = 0, dict(value=result)
- else:
- code, data = -1, {}
- return api_response(code, msg, data)
- def delete(self, request, *args, **kwargs):
- """
- 删除工单,仅用于管理员干预处理工单,loonflow管理后台的功能
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- # 校验工单权限
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- json_str = request.body.decode('utf-8')
- suggestion = ''
- if json_str:
- request_data_dict = json.loads(json_str)
- suggestion = request_data_dict.get('suggestion')
- flag, result = ticket_base_service_ins.ticket_admin_permission_check(ticket_id, username)
- if flag is False:
- return api_response(-1, result, {})
- flag, result = ticket_base_service_ins.delete_ticket(ticket_id, username, suggestion)
- if flag is False:
- return api_response(-1, result, {})
- else:
- return api_response(0, '', {})
- class TicketTransition(LoonBaseView):
- """
- 工单可以做的操作
- """
- def get(self, request, *args, **kwargs):
- request_data = request.GET
- ticket_id = kwargs.get('ticket_id')
- # username = request_data.get('username', '')
- username = request.META.get('HTTP_USERNAME')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(0, msg, dict(value=[]))
- if not username:
- return api_response(-1, '参数不全,请提供username', '')
- flag, result = ticket_base_service_ins.get_ticket_transition(ticket_id, username)
- if flag is False:
- code, data, msg = -1, {}, result
- else:
- code, data, msg = 0, dict(value=result.get('transition_dict_list')), ''
- return api_response(code, msg, data)
- class TicketFlowlog(LoonBaseView):
- """
- 工单流转记录
- """
- def get(self, request, *args, **kwargs):
- request_data = request.GET
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- per_page = int(request_data.get('per_page', 10))
- page = int(request_data.get('page', 1))
- ticket_data = int(request_data.get('ticket_data', 0))
- desc = int(request_data.get('desc', 1)) # 是否降序
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- if not username:
- return api_response(-1, '参数不全,请提供username', '')
- flag, result = ticket_base_service_ins.get_ticket_flow_log(ticket_id, username, per_page, page, ticket_data, desc)
- if flag is not False:
- paginator_info = result.get('paginator_info')
- data = dict(value=result.get('ticket_flow_log_restful_list'), per_page=paginator_info.get('per_page'),
- page=paginator_info.get('page'), total=paginator_info.get('total'))
- code, msg, = 0, ''
- else:
- code, data = -1, ''
- return api_response(code, msg, data)
- class TicketFlowStep(LoonBaseView):
- """
- 工单流转step: 用于显示工单当前状态的step图(线形结构,无交叉)
- """
- def get(self, request, *args, **kwargs):
- request_data = request.GET
- ticket_id = kwargs.get('ticket_id')
- # username = request_data.get('username', '') # 可用于权限控制
- username = request.META.get('HTTP_USERNAME')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- if not username:
- return api_response(-1, '参数不全,请提供username', '')
- flag, result = ticket_base_service_ins.get_ticket_flow_step(ticket_id, username)
- if flag is not False:
- data = dict(value=result.get('state_step_dict_list'), current_state_id=result.get('current_state_id'))
- code, msg, = 0, ''
- else:
- code, data = -1, ''
- return api_response(code, msg, data)
- class TicketState(LoonBaseView):
- """
- 工单状态
- """
- put_schema = Schema({
- 'state_id': And(int, lambda n: n != 0, error='state_id is needed and type should be int'),
- Optional('suggestion'): str,
- })
- def put(self, request, *args, **kwargs):
- """
- 修改工单状态
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- if not json_str:
- return api_response(-1, 'patch参数为空', {})
- request_data_dict = json.loads(json_str)
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- state_id = request_data_dict.get('state_id')
- suggestion = request_data_dict.get('suggestion', '')
- app_name = request.META.get('HTTP_APPNAME')
- # 调用来源应用是否有此工单对应工作流的权限校验
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- # 强制修改工单状态需要对应工作流的管理员或者超级管理员
- flag, result = ticket_base_service_ins.ticket_admin_permission_check(ticket_id, username)
- if flag is False:
- return api_response(-1, result, {})
- flag, result = ticket_base_service_ins.update_ticket_state(ticket_id, state_id, username, suggestion)
- if flag is False:
- return api_response(-1, result, {})
- else:
- return api_response(0, '', {})
- class TicketsStates(LoonBaseView):
- def get(self, request, *args, **kwargs):
- """
- 批量获取工单状态
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- request_data = request.GET
- # username = request_data.get('username', '') # 可用于权限控制
- username = request.META.get('HTTP_USERNAME')
- ticket_ids = request_data.get('ticket_ids') # 逗号隔开
- ticket_id_list = ticket_ids.split(',')
- ticket_id_list = [int(ticket_id) for ticket_id in ticket_id_list]
- flag, result = ticket_base_service_ins.get_tickets_states_by_ticket_id_list(ticket_id_list, username)
- if flag:
- code, msg, data = 0, '', result
- else:
- code, msg, data = -1, result, ''
- return api_response(code, msg, data)
- class TicketAccept(LoonBaseView):
- def post(self, request, *args, **kwargs):
- """
- 接单,当工单当前处理人实际为多个人时(角色、部门、多人都有可能, 注意角色和部门有可能实际只有一人)
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- result, msg = ticket_base_service_ins.accept_ticket(ticket_id, username)
- if result:
- code, msg, data = 0, msg, {}
- else:
- code, msg, data = -1, msg, ''
- return api_response(code, msg, data)
- class TicketDeliver(LoonBaseView):
- post_schema = Schema({
- 'target_username': And(str, lambda n: n != '', error='target_username is needed'),
- Optional('from_admin'): int,
- Optional('suggestion'): str,
- })
- def post(self, request, *args, **kwargs):
- """
- 转交操作会直接修改工单处理人,且工单状态不变,所以在使用的时候可以在前端做些提醒 避免用户把工单直接转交给下个人,从而干扰了工单的正常流转(
- 如用户提交了一个请假单,部门TL审批状态下,tl本来应该点击"同意",工单会自动流转到财务人员审批状态。 应该避免tl直接将工单转交给了某个财务)。这个地方后续会考虑怎么优化下,目前先在前端做提醒
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- request_data_dict = json.loads(json_str)
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- target_username = request_data_dict.get('target_username', '')
- suggestion = request_data_dict.get('suggestion', '')
- from_admin = request_data_dict.get('from_admin', 0)
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, {})
- if from_admin:
- flag, result = ticket_base_service_ins.ticket_admin_permission_check(ticket_id, username)
- if flag is False:
- return api_response(-1, result, {})
- else:
- # 非管理员操作,校验用户是否有处理权限
- flag, result = ticket_base_service_ins.ticket_handle_permission_check(ticket_id, username)
- if flag is False:
- return api_response(-1, result, {})
- if result.get('permission') is False:
- return api_response(-1, result.get('msg'), {})
- result, msg = ticket_base_service_ins.deliver_ticket(ticket_id, username, target_username, suggestion)
- if result:
- code, msg, data = 0, msg, result
- else:
- code, msg, data = -1, msg, ''
- return api_response(code, msg, data)
- class TicketAddNode(LoonBaseView):
- post_schema = Schema({
- 'target_username': And(str, lambda n: n != '', error='target_username is needed'),
- Optional('suggestion'): str,
- })
- def post(self, request, *args, **kwargs):
- """
- 加签,加签操作会修改工单处理人,工单状态不表
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- request_data_dict = json.loads(json_str)
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- target_username = request_data_dict.get('target_username', '')
- suggestion = request_data_dict.get('suggestion', '')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- result, msg = ticket_base_service_ins.add_node_ticket(ticket_id, username, target_username, suggestion)
- if result:
- code, msg, data = 0, msg, {}
- else:
- code, msg, data = -1, msg, ''
- return api_response(code, msg, data)
- class TicketAddNodeEnd(LoonBaseView):
- post_schema = Schema({
- Optional('suggestion'): str,
- })
- def post(self, request, *args, **kwargs):
- """
- 加签处理完成,加签完成操作后工单处理人回回到之前加签发起人
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- if not json_str:
- return api_response(-1, 'post参数为空', {})
- request_data_dict = json.loads(json_str)
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- suggestion = request_data_dict.get('suggestion', '')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- result, msg = ticket_base_service_ins.add_node_ticket_end(ticket_id, username, suggestion)
- if result:
- code, msg, data = 0, msg, {}
- else:
- code, msg, data = -1, msg, ''
- return api_response(code, msg, data)
- class TicketField(LoonBaseView):
- def patch(self, request, *args, **kwargs):
- """
- 修改工单字段
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- if not json_str:
- return api_response(-1, 'post参数为空', {})
- request_data_dict = json.loads(json_str)
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- result, msg = ticket_base_service_ins.update_ticket_field_value(ticket_id, request_data_dict)
- if result:
- code, msg, data = 0, msg, {}
- else:
- code, msg, data = -1, msg, ''
- return api_response(code, msg, data)
- class TicketScriptRetry(LoonBaseView):
- def post(self, request, *args, **kwargs):
- """
- 重新执行工单脚本(用于脚本执行出错的情况), 也可用于hook执行失败的情况
- :return:
- """
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- app_name = request.META.get('HTTP_APPNAME')
- app_permission_check, msg = account_base_service_ins.app_ticket_permission_check(app_name, ticket_id)
- if not app_permission_check:
- return api_response(-1, msg, '')
- if not username:
- api_response(-1, 'need arg username', '')
- result, msg = ticket_base_service_ins.retry_ticket_script(ticket_id, username)
- if result:
- code, msg, data = 0, 'Ticket script or hook retry start successful', {}
- else:
- code, msg, data = -1, msg, {}
- return api_response(code, msg, data)
- class TicketComment(LoonBaseView):
- post_schema = Schema({
- 'suggestion': And(str, lambda n: n != '', error='suggestion is needed'),
- })
- def post(self, request, *args, **kwargs):
- """
- 添加评论
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- if not json_str:
- return api_response(-1, 'post参数为空', {})
- request_data_dict = json.loads(json_str)
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- suggestion = request_data_dict.get('suggestion', '')
- result, msg = ticket_base_service_ins.add_comment(ticket_id, username, suggestion)
- if result:
- code, msg, data = 0, 'add ticket comment successful', {}
- else:
- code, msg, data = -1, msg, ''
- return api_response(code, msg, data)
- class TicketHookCallBack(LoonBaseView):
- def post(self, request, *args, **kwargs):
- """
- 工单hook回调,用于hoot请求后,被请求方执行完任务后回调loonflow,以触发工单继续流转
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- ticket_id = kwargs.get('ticket_id')
- json_str = request.body.decode('utf-8')
- if not json_str:
- return api_response(-1, 'post参数为空', {})
- request_data_dict = json.loads(json_str)
- app_name = request.META.get('HTTP_APPNAME')
- result, msg = ticket_base_service_ins.hook_call_back(ticket_id, app_name, request_data_dict)
- if result:
- code, msg, data = 0, 'add ticket comment successful', {}
- else:
- code, msg, data = -1, msg, ''
- return api_response(code, msg, data)
- class TicketParticipantInfo(LoonBaseView):
- def get(self, request, *args, **kwargs):
- """
- 工单当前处理人详情,调用方后端可用获取处理人信息后提供催办等功能
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- ticket_id = kwargs.get('ticket_id')
- flag, msg = ticket_base_service_ins.get_ticket_participant_info(ticket_id)
- if flag:
- code, msg, data = 0, '', msg
- else:
- code, msg, data = -1, msg, {}
- return api_response(code, msg, data)
- class TicketClose(LoonBaseView):
- def post(self, request, *args, **kwargs):
- """
- 强制关闭工单
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- json_str = request.body.decode('utf-8')
- ticket_id = kwargs.get('ticket_id')
- request_data_dict = json.loads(json_str)
- username = request.META.get('HTTP_USERNAME')
- suggestion = request_data_dict.get('suggestion', '')
- flag, result = ticket_base_service_ins.close_ticket_permission_check(ticket_id, username)
- if flag is False:
- return api_response(-1, result, {})
- flag, msg = ticket_base_service_ins.close_ticket(ticket_id, username, suggestion)
- if flag:
- code, msg, data = 0, '', msg
- else:
- code, msg, data = -1, msg, {}
- return api_response(code, msg, data)
- class TicketsNumStatistics(LoonBaseView):
- def get(self, request, *args, **kwargs):
- """
- 工单个数统计
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- start_date = kwargs.get('start_date', '')
- end_date = kwargs.get('end_date', '')
- username = request.META.get('HTTP_USERNAME')
- flag, result = ticket_base_service_ins.get_ticket_num_statistics(start_date, end_date, username)
- if flag:
- return api_response(0, '', result.get('result_list'))
- else:
- return api_response(-1, result, {})
- class TicketRetreat(LoonBaseView):
- def post(self, request, *args, **kwargs):
- """
- 撤回工单,允许创建人在指定状态撤回工单至初始状态,状态设置中开启允许撤回
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- ticket_id = kwargs.get('ticket_id')
- username = request.META.get('HTTP_USERNAME')
- json_str = request.body.decode('utf-8')
- request_data_dict = json.loads(json_str)
- suggestion = request_data_dict.get('suggestion', '')
- flag, result = ticket_base_service_ins.retreat_ticket(ticket_id, username, suggestion)
- if flag:
- return api_response(0, '', {})
- else:
- return api_response(-1, result, {})
- class UploadFile(LoonBaseView):
- def post(self, request, *args, **kwargs):
- """
- 上传文件
- :param request:
- :param args:
- :param kwargs:
- :return:
- """
- flag, result = ticket_base_service_ins.upload_file(request)
- if flag:
- return api_response(0, '', result)
- else:
- return api_response(-1, result, {})
|