钉钉python实现审批数据库设计

news/2024/7/3 4:14:34

为了实现工单系统,又不想自己去结合钉钉的组织架构实现一套审批流,所以采用钉钉的审批结合自己的系统去实现工单。

由钉钉实现审批流,软件实现查询,记录工单等。

在上一篇中已经实现了审批流程以及回调函数的实现和整个工单的逻辑,下面描述一下数据库的设计。

主要分为两个表去实现:

1. 工单的种类表,主要用于存储钉钉的工单种类或者想要用于操作的工单种类,即不是所有的工单都需要做记录操作。

表名:ticket_type

字段

字段类型

描述

id

int(11)

自增id,主键

process_code

varchar(64)

钉钉工单code码

name

varchar(64)

工单名称

url

varchar(256)

工单钉钉的申请页面地址

icon_url

tinyint(1)

图标地址

create_time

datetime

创建时间

update_time

datetime

修改时间

 

上述这些字段是钉钉的工单类型api会提供的,下面方法获取数据:

def getTicketType():
    Client = SecretClient(CORPID, SECRET) #dingtalk连接
    #用一个userid去获取这个userid的所有工单,如果工单很多,可以遍历执行,这里只有获取100个
    req = Client.bpms.process_listbyuserid(USERID, 0, 100) 
    process_top_vo = req['process_list']['process_top_vo']
    for p in process_top_vo:
        icon_url = p.get('icon_url', '')
        name = p.get('name', '')
        process_code = p.get('process_code', '')
        url = p.get('url', '')
        ticketType = TicketType.objects.filter(process_code=process_code)
        if ticketType:
            ticketType.update(icon_url=icon_url, name=name, url=url, update_time=datetime.datetime.now())
        else:
            TicketType.objects.create(process_code=process_code, icon_url=icon_url, name=name, url=url,
                                      type='', update_time=datetime.datetime.now())

 

2. 工单记录表,主要用于存储工单记录,通过钉钉回调过来的数据,然后记录在ticket_type里面的工单。

表名:ticket_record

字段

字段类型

描述

id

int(11)

自增id,主键

process_code

varchar(64)

钉钉工单code码(ticket_type)

process_instance_id

varchar(64)

工单的唯一编号

business_id

varchar(32)

审批实例业务编号

title

varchar(64)

审批实例标题

operation_records

longtext

操作记录列表

originator_dept_id

varchar(32)

发起的部门(钉钉部门)

originator_userid

varchar(64)

发起人(userid)

form_component_values

longtext

表单详情列表

status

varchar(32)

审批状态

result

varchar(32)

审批结果,分为 agree 和 refuse

cc_userids

varchar(1000)

抄送人

participant

varchar(64)

当前处理人(userid)

relation

varchar(1000)

关联人(记录哪些人操作过)

tasks

longtext

已审批任务列表,可以通过此列表获取已审批人

is_operation

tinyint

是否操作(用于后续自动化操作的记录)

create_time

datetime

创建时间

update_time

datetime

修改时间

 

这个通过钉钉回调过来的信息,然后通过钉钉的api去获取钉钉的工单实例详情:

请求方式:POST(HTTPS)
请求地址https://oapi.dingtalk.com/topapi/processinstance/get?access_token=ACCESS_TOKEN
参数说明

名称类型是否必须示例值描述
process_instance_idString必须1a2b-3e4d审批实例id

 

def getTicketRecord(process_instance_id):#此参数可以用钉钉的回调中获取
    '''
    获取工单详情
    :param process_instance_id: 工单的id
    :return:
    '''
    url = 'https://oapi.dingtalk.com/topapi/processinstance/get?access_token=' + getToken()
    data = {
        'process_instance_id': process_instance_id
    }
    #获取工单的详情
    req = requests.post(url, data=json.dumps(data))
    content = json.loads(req.text)['process_instance']
    originator_userid = content.get('originator_userid')
    business_id = content.get('business_id')
    title = content.get('title')
    operation_records = content.get('operation_records')
    originator_dept_id = content.get('originator_dept_id')
    form_component_values = content.get('form_component_values')
    tasks = content.get('tasks')
    status = content.get('status')
    result = content.get('result')
    cc_userids = content.get('cc_userids')
    relation = []
    participant = ''
    for task in tasks:
        userid = str(task.get('userid', ''))
        if task.get('task_result') == 'NONE' and task.get('task_status') == 'RUNNING':  #如果是这个状态的值,那么就是当前需要操作的
            if not participant:
                participant += userid
            else:
                participant = participant + ',' + userid
        if userid:
            if userid not in relation:
                relation.append(userid)  #所有做过操作的人,用于展示界面上相关的工单列表
    if originator_userid not in relation:
        relation.append(originator_userid)
    relation = ','.join(relation)
    participant = participant

将上述的值存到数据库中即可。

综合,完成一个所有的钉钉流程:

1. 钉钉填写工单:回调到工单系统,工单系统记录下操作。

2. 工单状态的改变:回调到工单系统,工单系统记录下操作。

3. 判断工单是否结束,结束了之后,是否要进行自动化处理,自动化处理要根据具体的项目来实现,达到一个完整的工单,人工只需要进行审批,所有的操作都是自动化。

目前只做了简单的几个自动化,在回调的时候判断函数:

#满足条件进行自动的操作
if  status == 'COMPLETED' and result == 'agree':#判断是否结束,且是同意的
    t = TicketRecord.objects.filter(process_instance_id=processInstanceId) 获取工单详情
    typeTicket = ''
    try:
        ticket = TicketType.objects.get(process_code=process_code)
        process_code = ticket.process_code #此处加了
    except Exception as e:
        print(e)

    if t and not t[0].is_operation:#判断没有进行操作过则进行自动化操作
        if process_code == '12345698765432876543': #判断要进行哪种自动化
            res, msg = attach(processInstanceId)#自动化函数,此处可以用celery异步操作。

 

回调的时候说一下一个容易出错的地方:

'bpms_task_change', 'bpms_instance_change'这两个回调在创建等操作的时候会同时回调回来,这个时候就要注意数据库的操作,避免写入相同的数,避免进行多次操作,需要自己去把控。

 

 

 


http://www.niftyadmin.cn/n/2813901.html

相关文章

高阶组件 基础模板 react

function Dialog(Component){return class extends React.Component{render(){return <Component />}}}class DialogComponent extends React.Component{render(){return <div classNamebox>凌晨两点半</div>}}let DialogDom Dialog(DialogComponent )…

高阶组件

高阶组件 高阶组件是什么他能给我们带来什么他的优点是什么

react 路由基础配置解释 模板 精简

路由的基本用法 // 下载第三方包 react-router-domimport {BrowserRouter,Route,Redirect,Link,NavLink} from react-router-dom;//在组件当中class Index extends Component{render(){return <BrowserRouter><Route path{} component{} exact/></BrowserRoute…

js监听浏览器变化的函数,大于500px时,打印console.log('hello'),且只打印一次

let str ;window.onresize function(){if(document.body.clientWidth> 500){if(str ){strhello;console.log(str);}else{return;}}}

redux 解析

下载第三方包 && 并且引入 const { createStore } require(redux);console.log( createStore ); // [Function: createStore] 是一个函数可以进行调用const { createStore } require(redux);let reducer (state,action)>{// action默认是{ type: redux/INITb.2…

微信小程序开发 模拟器上 获取不到input 框的焦点的解决办法 原因

在输入框的位置长按 Windows10笔记本上运行微信小程序开发者工具&#xff0c;输入框&#xff08;input&#xff0c;textarea&#xff09;没有焦点&#xff0c;只能在真机调试&#xff0c;效率太低。 后来发现是Window10对笔记本高分屏支持不好&#xff0c;要DPI缩放&#xff0…

Cannot find module '@babel/plugin-transform-react-jsx'

这个是因为丢包 解决办法 将node_modules删除重新下载就OK了

VM11172:1 thirdScriptError sdk uncaught third Error Cannot read property 'toString' of undefined

VM11172:1 thirdScriptError sdk uncaught third Error Cannot read property toString of undefined TypeError: Cannot read property toString of undefined解决方案引入的文件中存在问题 在引入文件中查找如果引入文件中内容没用 删除即可