钉钉离职OA审批提醒审批人审批通知脚本
个人博客
个人博客直达地址
网站不断完善中里面拥有大量的脚本,并且源码完全开放 欢迎纯白嫖。
效果图
概述
此脚本通过钉钉API自动化地发送离职审批通知。它会从指定的审批流程中获取相关审批实例,并在符合条件时,向相关人员发送离职通知。这对于企业人力资源管理尤其重要,能够确保在离职员工的最后工作日及时通知相关人员,便于工作交接。
功能说明
主要功能
-
获取钉钉Access Token:
- 脚本通过
get_access_token()
方法从钉钉服务器获取访问令牌(Access Token),以用于后续的API请求。
- 脚本通过
-
日期计算:
- 脚本计算当前日期时间以及两个月前的日期,并将这些日期转换为Unix时间戳(以毫秒为单位),以便在API请求中使用。
-
审批实例获取:
- 通过
Sample.create_client()
方法创建钉钉API客户端,循环获取指定审批流程的实例ID列表。
- 通过
-
审批实例详情提取:
- 对于每个审批实例,脚本会提取表单中的“离职人员姓名”、“最后工作日”、“离职交接人”等关键信息,并判断是否需要发送通知。
-
钉钉消息发送:
- 在符合条件的情况下,脚本会自动向离职人员的交接人发送钉钉消息,提醒他们即将进行的交接工作。
使用方法
-
前置条件:
- 您需要具备钉钉企业管理员权限,并获取应用的
appkey
和appsecret
。 - 请将脚本中的
your_appkey_here
和your_appsecret_here
替换为实际的appkey
和appsecret
。 - 替换脚本中的
your_process_code_here
为实际的审批流程代码。 - 替换
your_webhook_url_here
和www.your_url_here
为实际的钉钉Webhook URL和跳转链接。
- 您需要具备钉钉企业管理员权限,并获取应用的
-
运行脚本:
- 直接在终端运行此脚本,例如:
python3 script.py
。 - 脚本将自动执行,并在控制台输出相关信息和调试内容。
- 直接在终端运行此脚本,例如:
-
注意事项:
- 时间戳计算:脚本依赖于日期和时间的计算,确保系统时间设置正确。
- API调用频率:如果钉钉API调用频率超出限制,可能会导致部分请求失败。
- 网络连接:脚本需要稳定的网络连接以访问钉钉API。
- 异常处理:脚本中包含异常处理逻辑,但建议定期查看日志以确保脚本运行正常。
- 重复通知:脚本使用
sent_messages
集合来防止同一审批实例的重复通知。
代码块
#!/usr/bin/python3
# 导入所需库
import dingtalk.api
import re
import sys
from typing import List
from alibabacloud_dingtalk.workflow_1_0.client import Client as dingtalkworkflow_1_0Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dingtalk.workflow_1_0 import models as dingtalkworkflow__1__0_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
from dateutil.parser import parse
from dateutil.parser._parser import ParserError
import time
import requests
start_time = time.time()
# 获取钉钉API的access_token
def get_access_token():
req = dingtalk.api.OapiGettokenRequest("https://oapi.dingtalk.com/gettoken")
req.appkey = "your_appkey_here" # Replace with your actual appkey
req.appsecret = "your_appsecret_here" # Replace with your actual appsecret
try:
resp = req.getResponse()
print(resp) # 打印resp以查看返回值
access_token = resp.get('access_token')
return access_token
except Exception as e:
print(e)
return None # 在发生异常时返回None
access_token = get_access_token()
if access_token is not None:
print("access_token的值为:" + access_token)
else:
print("access_token的值为:None")
# 钉钉群机器人Webhook URL
webhook_url = "your_webhook_url_here" # Replace with your actual webhook URL
# 定义当前日期时间、两个月前的日期
current_datetime = datetime.now()
current_date = current_datetime.date()
two_months_ago_date = current_date - relativedelta(months=2)
# 计算当前日期时间、当前日期、两个月前的日期的Unix时间戳(毫秒)
epoch = datetime(1970, 1, 1)
current_datetime_timestamp_ms = int((current_datetime - epoch).total_seconds()) * 1000
current_date_timestamp_ms = int((current_date - epoch.date()).total_seconds()) * 1000
two_months_ago_date_timestamp_ms = int((two_months_ago_date - epoch.date()).total_seconds()) * 1000
print("当前日期和时间:", current_datetime)
print("当前日期和时间的Unix时间戳(毫秒):", current_datetime_timestamp_ms)
print("当前日期:", current_date)
print("当前日期的Unix时间戳(毫秒):", current_date_timestamp_ms)
print("两个月前的日期:", two_months_ago_date)
print("两个月前的日期的Unix时间戳(毫秒):", two_months_ago_date_timestamp_ms)
class Sample:
def __init__(self):
pass
# 创建钉钉API客户端
@staticmethod
def create_client() -> dingtalkworkflow_1_0Client:
config = open_api_models.Config()
config.protocol = 'https'
config.region_id = 'central'
return dingtalkworkflow_1_0Client(config)
# 主要功能实现
@staticmethod
def main(args: List[str]) -> None:
client = Sample.create_client()
list_process_instance_ids_headers = dingtalkworkflow__1__0_models.ListProcessInstanceIdsHeaders()
list_process_instance_ids_headers.x_acs_dingtalk_access_token = access_token
next_token = 0
sent_messages = set() # 用于存储已发送过的消息,防止重复发送
# 循环获取审批实例列表
while True:
list_process_instance_ids_request = dingtalkworkflow__1__0_models.ListProcessInstanceIdsRequest(
start_time=two_months_ago_date_timestamp_ms,
end_time=current_datetime_timestamp_ms,
process_code='your_process_code_here', # Replace with your actual process code
next_token=next_token,
max_results=20
)
try:
# 获取审批实例列表
response = client.list_process_instance_ids_with_options(list_process_instance_ids_request,
list_process_instance_ids_headers,
util_models.RuntimeOptions())
# 获取下一页的Token
fenye = response.body.result.next_token
print("nextToken 的值为:", fenye)
if not fenye:
break
# 获取审批实例的ID列表
list_values = response.body.result.list
print("processInstanceId的值为:", list_values)
# 遍历审批实例
for process_instance_id in list_values:
userid = ""
get_process_instance_headers = dingtalkworkflow__1__0_models.GetProcessInstanceHeaders()
get_process_instance_headers.x_acs_dingtalk_access_token = access_token
get_process_instance_request = dingtalkworkflow__1__0_models.GetProcessInstanceRequest(
process_instance_id=process_instance_id
)
try:
# 获取单个审批实例的详情
instance_response = client.get_process_instance_with_options(get_process_instance_request,
get_process_instance_headers,
util_models.RuntimeOptions())
# 获取表单中的值
form_component_values = instance_response.body.result.form_component_values
leaving_employee_name = ""
last_working_day = ""
handover_person = ""
for component in form_component_values:
if component.name == "离职人员姓名":
leaving_employee_name = component.value
elif component.component_type == "DDDateField":
if component.name == "最后工作日" or component.name == "最后工作日(不计算假期)":
last_working_day = component.value
elif component.name == "离职交接人":
handover_person = component.value
# 解析最后工作日
last_working_day_dt = parse(last_working_day)
# 判断是否需要发送通知
if last_working_day_dt.date() == current_date and leaving_employee_name not in sent_messages:
qwe = str(instance_response)
# 从审批实例中提取当前审批人ID
pattern = r"'status': 'RUNNING', 'taskId': \d+, 'userId': '(\d+)'"
match = re.search(pattern, qwe)
if match:
userid = match.group(1)
print(userid)
else:
print("OA流程已完成", qwe)
continue
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 构造并发送钉钉消息
req = dingtalk.api.OapiMessageCorpconversationAsyncsendV2Request("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2")
req.agent_id = 2575041888 # Replace with your actual agent ID
req.userid_list = userid
req.msg = {
"msgtype": "action_card",
"action_card": {
"title": "OA离职审批通知",
"markdown": f"表单名称:员工离职审批 \n审批ID:{process_instance_id} \n离职人员姓名:{leaving_employee_name} \n最后工作日:{last_working_day} \n离职交接人:{handover_person} \n发送时间{current_time}",
"btn_json_list": [
{
"title": "OA离职审批通知",
"action_url": "www.your_url_here" # Replace with your actual URL
}
],
"btn_orientation": "0",
},
"userid_list": f"{userid}",
"to_all_user": False,
"agent_id": 2575041888, # Replace with your actual agent ID
}
try:
# 发送钉钉消息
resp = req.getResponse(access_token)
print(resp)
except Exception as e:
print(e)
except Exception as err:
print(f"遇到错误:{err}")
continue
except Exception as err:
if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
pass
break
next_token = fenye
end_time = time.time()
print(f"脚本执行总时间为: {end_time - start_time}秒")
if __name__ == '__main__':
Sample.main(sys.argv[1:])