Skip to content

Commit

Permalink
participant support get from post response
Browse files Browse the repository at this point in the history
  • Loading branch information
blackholll committed Oct 19, 2022
1 parent 6e7bc76 commit 9ed725d
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 6 deletions.
2 changes: 1 addition & 1 deletion apps/workflow/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class State(BaseModel):
enable_retreat = models.BooleanField('允许撤回', default=False, help_text='开启后允许工单创建人在此状态直接撤回工单到初始状态')

remember_last_man_enable = models.BooleanField('记忆最后处理人', default=False, help_text='开启后,到达此状态时会先检查之前是否有人在此状态处理过,如果有则处理人为最后一次处理的人')
participant_type_id = models.IntegerField('参与者类型id', default=1, blank=True, help_text='0.无处理人,1.个人,2.多人,3.部门,4.角色,5.变量(支持工单创建人,创建人的leader),6.脚本,7.工单的字段内容(如表单中的"测试负责人",需要为用户名或者逗号隔开的多个用户名),8.父工单的字段内容,10.hook。 初始状态请选择类型5,参与人填creator')
participant_type_id = models.IntegerField('参与者类型id', default=1, blank=True, help_text='0.无处理人,1.个人,2.多人,3.部门,4.角色,5.变量(支持工单创建人,创建人的leader),6.脚本(已废弃),7.工单的字段内容(如表单中的"测试负责人",需要为用户名或者逗号隔开的多个用户名),8.父工单的字段内容,10.hook,11.外部获取。 初始状态请选择类型5,参与人填creator')
participant = models.CharField('参与者', default='', blank=True, max_length=1000, help_text='可以为空(无处理人的情况,如结束状态)、username\多个username(以,隔开)\部门id\角色id\变量(creator,creator_tl)\脚本记录的id等,包含子工作流的需要设置处理人为loonrobot')

distribute_type_id = models.IntegerField('分配方式', default=1, help_text='1.主动接单(如果当前处理人实际为多人的时候,需要先接单才能处理) 2.直接处理(即使当前处理人实际为多人,也可以直接处理) 3.随机分配(如果实际为多人,则系统会随机分配给其中一个人) 4.全部处理(要求所有参与人都要处理一遍,才能进入下一步)')
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/pages/Workflow/WorkflowState/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -408,15 +408,16 @@ class WorkflowState extends Component<any, any> {
<Option value={3}>部门</Option>
<Option value={4}>角色</Option>
<Option value={5}>变量</Option>
<Option value={6}>脚本</Option>
{/*/!*<Option value={6}>脚本</Option>*!/ 已废弃*/}
<Option value={7}>工单字段</Option>
<Option value={8}>父工单字段</Option>
<Option value={10}>hook</Option>
<Option value={11}>外部获取</Option>
<Option value={0}></Option>
</Select>
</Form.Item>
<Form.Item name="participant"
label={<span>参与人<Tooltip title='个人(username)\多人(多个username以,隔开\部门(部门id,多个部门以逗号隔开)\角色(角色id)\变量(creator:工单的创建人,creator_tl:工单创建人的TL,多个变量逗号隔开)\脚本记录的id\工单字段(逗号隔开多个)\父工单字段(逗号隔开多个)等,需要在此状态创建子工单时需要设置此处处理人为loonrobot。 当处理人类型为hook方式时,处理人需要按照如下规则配置 {"hook_url":"http://xxx.com/xxx", "hook_token":"xxxx", "wait":true, "extra_info":"xxxx"}。详见文档'><QuestionCircleOutlined /></Tooltip></span>}
label={<span>参与人<Tooltip title='个人(username)\多人(多个username以,隔开\部门(部门id,多个部门以逗号隔开)\角色(角色id)\变量(creator:工单的创建人,creator_tl:工单创建人的TL,多个变量逗号隔开)\脚本记录的id\工单字段(逗号隔开多个)\父工单字段(逗号隔开多个)等,需要在此状态创建子工单时需要设置此处处理人为loonrobot。 当处理人类型为hook方式时,处理人需要按照如下规则配置 {"hook_url":"http://xxx.com/xxx", "hook_token":"xxxx", "wait":true, "extra_info":"xxxx"},外部获取配置规则:{"external_url":"http://xxx.com/xxx", "external_token":"xxxx", "extra_info":"xxxx"}。详见文档'><QuestionCircleOutlined /></Tooltip></span>}
>
<Input />

Expand Down
1 change: 1 addition & 0 deletions service/common/constant_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def __init__(self):
self.PARTICIPANT_TYPE_FIELD = 7 # 工单字段(用户名类型的)
self.PARTICIPANT_TYPE_PARENT_FIELD = 8 # 父工单字段(用户名类型的)
self.PARTICIPANT_TYPE_HOOK = 10 # hook方式,当工单状态叨叨处理人类型配置为kook的状态时,loonflow将触发一个hook请求,被请求方可以执行有些自动化操作然后回调loonflow,
self.PARTICIPANT_TYPE_FROM_EXTERNAL = 11 # 来自外部,通过触发请求获取当前的处理人

self.TRANSITION_TYPE_COMMON = 1 # 常规流转
self.TRANSITION_TYPE_TIMER = 2 # 定时器流转
Expand Down
31 changes: 31 additions & 0 deletions service/ticket/ticket_base_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import copy
import json
import datetime
import logging
import random

import redis
Expand Down Expand Up @@ -2062,6 +2063,36 @@ def get_ticket_state_participant_info(cls, state_id: int, ticket_id: int=0, tick
elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_HOOK:
destination_participant = '***' # 敏感数据,不保存工单基础表中

elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_FROM_EXTERNAL:
import requests
external_config = json.loads(participant)
external_url = external_config.get('external_url')
external_token = external_config.get('external_token')
extra_info = external_config.get('extra_info')

flag, msg = common_service_ins.gen_hook_signature(external_token)
if not flag:
return False, msg
flag, all_ticket_data = ticket_base_service_ins.get_ticket_all_field_value(ticket_id)
if extra_info is not None:
all_ticket_data.update(dict(extra_info=extra_info))
try:
r = requests.post(external_url, headers=msg, json=all_ticket_data, timeout=10)
result = r.json() # {code:0, msg:'', data:'zhangsan,lisi'}
if result.get('data').split(',') > 1:
destination_participant_type_id = constant_service_ins.PARTICIPANT_TYPE_MULTI
else:
destination_participant_type_id = constant_service_ins.PARTICIPANT_TYPE_PERSONAL
destination_participant = result.get('data')
except Exception as e:
import logging
import traceback
logger = logging.getLogger('django')
logger.error('get external participant error:')
logger.error(traceback.format_exc())
destination_participant_type_id = constant_service_ins.PARTICIPANT_TYPE_PERSONA
destination_participant = 'admin'

# 参与人去重复+类型修正
if destination_participant_type_id in (constant_service_ins.PARTICIPANT_TYPE_PERSONAL, constant_service_ins.PARTICIPANT_TYPE_MULTI):
destination_participant_list = destination_participant.split(',')
Expand Down
12 changes: 10 additions & 2 deletions sphinx_docs/source/manage/workflow_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ loonflow发送hook请求时,header头中将包含signature 和timestamp。
使用场景如:运维处理中状态下处理人有A、B、C,其中A处理了工单,然后到达发起人确认状态时,发起人发现处理的有问题,
那么发起人可能是希望将工单退回到之前处理的A。而不是A、B、C都收到工单

参与人类型: 参与人类型包括个人、多人、部门、角色、脚本(建议使用hook替代)、工单字段、父工单字段、hook、无。
参与人类型: 参与人类型包括个人、多人、部门、角色、工单字段、父工单字段、hook、外部获取、无。
注意:如果需要在此状态创建子工单,需要将参与人类型设置为个人,参与人使用loonrobot

参与人:参与人信息根据参与人类型不同而不同,如果参与人类型是个人,那么参与人需要填写用户的username。 如果参与人类型是多人,
Expand All @@ -150,6 +150,8 @@ wait的值可以是true或者false,如果wait的值是false那么工单触发hoo
即code=-1 或者服务端无响应或者http status非200工单会标记script_run_last_result为False,你可以调用“重试工单脚本/任务”重新触发hook),
如果wait的值是true那么工单触发hook后会停留在当前状态,直到hook方回调(回调逻辑见文档中“工单相关接口”-"工单hook回调")loonflow成功
(请求参数中result=True)后工单的状态才继续流转。extra_info(非必填)可以用于传一些额外的信息,loonflow会将这个信息连同工单信息传给hook服务端。
如果参与人类型是'外部获取',参与人信息需要填写{"external_url":"http://www.xx.com", "external_token":"xxx", "extra_info":""},
系统将根据你配置的地址发起post请求,将结果中的内容作为参与人。

::

Expand All @@ -158,7 +160,7 @@ wait的值可以是true或者false,如果wait的值是false那么工单触发hoo
ori_str = timestamp + token
signature = hashlib.md5(ori_str.encode(encoding='utf-8')).hexdigest()

hook触发时loonflow向hook_url服务端post请求时带的数据如下:
hook触发时loonflow向hook_url服务端post请求时带的数据如下(外部获取类型post请求数据格式也如此)

::

Expand All @@ -171,6 +173,12 @@ hook触发时loonflow向hook_url服务端post请求时带的数据如下:
"extra_info": "xxxx", // 此处如果你配置hook的时候指定了extra_info那么会有这个字段,如果没配置就没这个信息
}

对于hook类型你的hook服务端需要response status code 200, 内容为json格式,包含code,msg字段,code为0 表示hook服务端已成功收到请求,并正常处理。
如{"code":200, "msg":"ok"},其中msg会被记录到工单的flowlog中,你可以在你处理出错时将出错原因填充到msg字段。
对于外部获取类型,你的external_url的服务端需要response status code 200,内容为json格式,包含code,msg, data字段,如{"code":0, "msg":"xxx",
"data":"zhansgan,lisi"}, 其中data字段中包含的是你需要将此工单的处理人设置为哪些username, 多个username使用逗号隔开


分配方式: 分配方式包括直接处理、主动接单、随机分配、全部处理。如果设置为直接处理,工单的当前处理人可以直接点击配置的流
转(如同意、拒绝、完成)来处理。如果设置为主动接单,则当前处理人需要先接单,然后才可以按照配置的流转来处理(表现形式为获取用
户可执行的操作接口只会返回接单这个流转,具体参考关于接单接口的纤细描述)。 如果设置为随机分配,那么系统会自动将工单处理人设置
Expand Down
2 changes: 1 addition & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def flow_hook_task(ticket_id):
if participant_type_id != constant_service_ins.PARTICIPANT_TYPE_HOOK:
return False, ''
hook_config = state_obj.participant
hook_config_dict= json.loads(hook_config)
hook_config_dict = json.loads(hook_config)
hook_url = hook_config_dict.get('hook_url')
hook_token = hook_config_dict.get('hook_token')
wait = hook_config_dict.get('wait')
Expand Down

0 comments on commit 9ed725d

Please sign in to comment.