370 lines
14 KiB
Python
370 lines
14 KiB
Python
import pandas as pd
|
|
import pandas as pd
|
|
import numpy as np
|
|
import requests
|
|
import json
|
|
import time
|
|
import re
|
|
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
from pathlib import Path
|
|
from urllib.parse import quote
|
|
from io import BytesIO
|
|
|
|
ROOT = Path('.').absolute() # 当前工作目录
|
|
|
|
def generateToken() -> str:
|
|
""" 生成 token """
|
|
|
|
token_api = 'https://api.dingtalk.com/v1.0/oauth2/accessToken'
|
|
|
|
# 该信息在钉钉开放应用中
|
|
data = {
|
|
"appKey": "ding5kqocon5s9oph5uq",
|
|
"appSecret": 'HL1jgsIIfLAC0eTH0A1m4mwxUDqbgsiPeCCGGE3ocM6qJBTIW7Ivt9drxF_Z4Kb_'
|
|
}
|
|
|
|
res = requests.post(token_api, json=data)
|
|
token = res.json()['accessToken']
|
|
|
|
return token
|
|
|
|
def read_processes_instances(token, formUuid, createFromTimeGMT, createToTimeGMT, page, n):
|
|
""" 函数功能:读取流程表单的所有数据 """
|
|
|
|
api = f'https://api.dingtalk.com/v1.0/yida/processes/instances?pageNumber={page}&pageSize={n}'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
|
|
formData = {
|
|
"appType": "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken": "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"userId": "yida_pub_account", # 超级管理员账号
|
|
"language": "zh_CN",
|
|
"formUuid": formUuid,
|
|
"createFromTimeGMT": createFromTimeGMT,
|
|
"createToTimeGMT": createToTimeGMT,
|
|
# "searchFieldJson": json.dumps(searchField), # 如果增加上这一项会要求升级宜搭存储
|
|
"instanceStatus": "RUNNING"
|
|
}
|
|
|
|
res = requests.post(api, headers=headers, json=formData)
|
|
return res.json()
|
|
|
|
def read_instances(token, formUuid, page, n):
|
|
""" 函数功能:读取流程表单的所有数据 """
|
|
|
|
api = f'https://api.dingtalk.com//v1.0/yida/forms/instances/search?pageNumber={page}&pageSize={n}'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
|
|
formData = {
|
|
"appType": "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken": "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"userId": "yida_pub_account", # 超级管理员账号
|
|
"language": "zh_CN",
|
|
"formUuid": formUuid,
|
|
# "searchFieldJson": json.dumps(searchField), # 如果增加上这一项会要求升级宜搭存储
|
|
"instanceStatus": "RUNNING"
|
|
}
|
|
|
|
res = requests.post(api, headers=headers, json=formData)
|
|
return res.json()
|
|
|
|
def timeStamp(timeNum):
|
|
""" 函数功能:将时间戳(毫秒) 转化为时间日期格式"""
|
|
timeStamp = float(timeNum/1000)
|
|
timeArray = time.localtime(timeStamp)
|
|
otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
|
|
return otherStyleTime
|
|
|
|
def get_time_range_minute(n):
|
|
""" 获取近n分钟的时间戳(单位是毫秒)"""
|
|
|
|
def delay_time(time_str, years=0, months=0, days=0, hours=0, minutes=0, seconds=0):
|
|
if type(time_str) == str:
|
|
time_str = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
|
|
ret = time_str + relativedelta(years=years, months=months, days=days, hours=hours, minutes=minutes, seconds=seconds)
|
|
return ret
|
|
|
|
# 获得当前时间
|
|
now_time = datetime.now()
|
|
endTime = int(time.mktime(time.strptime(now_time.strftime('%Y/%m/%d %H:%M:%S'), '%Y/%m/%d %H:%M:%S'))) * 1000 - 1000
|
|
# n小时前的时间
|
|
ret2 = delay_time(now_time, minutes=-n)
|
|
startTime = int(time.mktime(time.strptime(ret2.strftime('%Y/%m/%d %H:%M:%S'), '%Y/%m/%d %H:%M:%S'))) * 1000
|
|
|
|
# print(f'时间区间:[{startTime}-{endTime}]')
|
|
return startTime, endTime
|
|
|
|
def get_approval_records(token: str, processInstanceId: str):
|
|
""" 函数功能:获取流程表单的审批记录 --F6客户服务 应用 """
|
|
appType = "APP_UYZ0KG6L0CCNV80GZ66O"
|
|
systemToken = "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2"
|
|
userId = "yida_pub_account"
|
|
|
|
api = f'https://api.dingtalk.com/v1.0/yida/processes/operationRecords?appType={appType}&systemToken={systemToken}&userId={userId}&language=zh_CN&processInstanceId={processInstanceId}'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
|
|
res = requests.get(api, headers=headers)
|
|
print('获取流程表单的审批记录')
|
|
return res.json()
|
|
|
|
def forms_isDone(TOKEN: str, FORMID: str, CREATE_FROM, CREATE_TO,PAGES,processInstanceId,isDone_id):
|
|
'''
|
|
返回isDone_id 对应的控件内容
|
|
'''
|
|
for i in range(1, PAGES+1):
|
|
form_data = read_processes_instances(token=TOKEN, formUuid=FORMID, page=i, n=100)
|
|
for data in form_data.get('data'):
|
|
processInstanceId_1 = data.get('processInstanceId')
|
|
if processInstanceId_1 == processInstanceId:
|
|
isDone = data.get('data').get(isDone_id)
|
|
return isDone
|
|
|
|
def aggree_approval(token: str, taskId: str, processInstanceId: str, formData: dict):
|
|
""" 函数功能:同意审批节点 --F6客户服务 应用 """
|
|
api = f'https://api.dingtalk.com/v1.0/yida/tasks/execute'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
|
|
payload = {
|
|
"outResult": "AGREE",
|
|
"appType": "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken": "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"remark": "同意(接口自动)",
|
|
"formDataJson": json.dumps(formData, cls=NpEncoder),
|
|
"processInstanceId": processInstanceId,
|
|
# "userId": "yida_pub_account",
|
|
"userId": "2268275546837446",
|
|
"language": "zh_CN",
|
|
"taskId": int(taskId)
|
|
}
|
|
|
|
res = requests.post(api, headers=headers, json=payload)
|
|
print('同意审批节点')
|
|
return res
|
|
|
|
def switch(token: str, processInstanceId: str, formData: dict):
|
|
""" 函数说明:
|
|
开关 程序调用时避免 重复进行(执行间隔 小于 单次执行时间时 发送 重复处理)
|
|
"""
|
|
api = f'https://api.dingtalk.com//v1.0/yida/forms/instances'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
|
|
payload = {
|
|
"appType" : "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken" : "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"userId" : "yida_pub_account", # 管理员
|
|
"language" : "zh_CN",
|
|
"useLatestVersion" : "false",
|
|
"formInstanceId" : processInstanceId,
|
|
"updateFormDataJson" : json.dumps(formData, cls=NpEncoder),
|
|
}
|
|
|
|
res = requests.put(api, headers=headers, json=payload)
|
|
print('开关 程序调用时避免 重复进行(执行间隔 小于 单次执行时间时 发送 重复处理)')
|
|
|
|
def update_form_staff(TOKEN: str,processInstanceId,staff_id,ModifiedField_value):
|
|
""" 函数功能:员工更新表单内容 """
|
|
api = f'https://api.dingtalk.com//v1.0/yida/forms/instances'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": TOKEN
|
|
}
|
|
data_new = {
|
|
ModifiedField_value:[staff_id]
|
|
}
|
|
payload = {
|
|
"appType" : "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken" : "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"userId" : "yida_pub_account", # 曹伟 id
|
|
"language" : "zh_CN",
|
|
"useLatestVersion" : "false",
|
|
"formInstanceId" : processInstanceId,
|
|
"updateFormDataJson" : json.dumps(data_new, cls=NpEncoder),
|
|
}
|
|
|
|
res = requests.put(api, headers=headers, json=payload)
|
|
print('员工更新表单内容')
|
|
return res
|
|
|
|
def get_staffID(TOKEN: str,staff_name):
|
|
""" 函数功能:通过员工名称获取员工id"""
|
|
# 读取员工对应关系:宜搭员工-ID对应表
|
|
TOKEN = generateToken()
|
|
FORMID = "FORM-EA866E715PF9YA7ECCAGSABX91Q72PVA3WRFL6" # 宜搭员工-ID对应表 FORM-EA866E715PF9YA7ECCAGSABX91Q72PVA3WRFL6
|
|
# 读取流程表单数据
|
|
form_data = read_instances(token=TOKEN, formUuid=FORMID, page=1, n=100)
|
|
PAGES = form_data.get('totalCount')//100 + 1
|
|
|
|
ALL_DATA_staff = []
|
|
""" 获取全量数据 """
|
|
for i in range(1, PAGES+1):
|
|
# form_data = read_processes_instances(token=TOKEN, formUuid=FORMID, createFromTimeGMT=CREATE_FROM, createToTimeGMT=CREATE_TO, page=i, n=100, searchField={'textField_l7if5ff9': '否'})
|
|
form_data = read_instances(token=TOKEN, formUuid=FORMID, page=i, n=100)
|
|
for data in form_data.get('data'):
|
|
ALL_DATA_staff.append(data)
|
|
res_new = [v['formData']['textField_lfrw3u59'] for v in ALL_DATA_staff if v['formData']['textField_lfrw3u58']== staff_name]
|
|
print('通过员工名称获取员工id')
|
|
return res_new
|
|
|
|
def get_type(TOKEN: str,ModifiedField_value,Form_id):
|
|
""" 函数功能:通过唯一标识获取控件类型"""
|
|
api = f'https://api.dingtalk.com/v1.0/yida/forms/formFields?appType=APP_UYZ0KG6L0CCNV80GZ66O&systemToken=XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2&formUuid='+Form_id+'&userId=yida_pub_account'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": TOKEN
|
|
}
|
|
|
|
|
|
res = requests.get(api, headers=headers)
|
|
cnew = res.json().get('result')
|
|
componentName = [i.get('componentName') for i in cnew if i.get('fieldId')== ModifiedField_value ]
|
|
print('通过唯一标识获取控件类型')
|
|
return componentName
|
|
|
|
def update_text(TOKEN: str, processInstanceId, formData):
|
|
""" 函数说明:更新单行文本控件内容
|
|
"""
|
|
api = f'https://api.dingtalk.com//v1.0/yida/forms/instances'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": TOKEN
|
|
}
|
|
payload = {
|
|
"appType" : "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken" : "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"userId" : "yida_pub_account", # 管理员
|
|
"language" : "zh_CN",
|
|
"useLatestVersion" : "false",
|
|
"formInstanceId" : processInstanceId,
|
|
"updateFormDataJson" : json.dumps(formData, cls=NpEncoder),
|
|
}
|
|
|
|
res = requests.put(api, headers=headers, json=payload)
|
|
print('更新单行文本控件内容')
|
|
return res
|
|
def read_instances_V2(token, formUuid, createFromTimeGMT, createToTimeGMT, page, n):
|
|
""" 函数功能:读取流程表单的所有数据 """
|
|
|
|
api = f'https://api.dingtalk.com//v1.0/yida/forms/instances/search'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
|
|
formData = {
|
|
"appType": "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken": "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"userId": "yida_pub_account", # 超级管理员账号
|
|
"language": "zh_CN",
|
|
"formUuid": formUuid,
|
|
'pageNumber':page,
|
|
'pageSize':n,
|
|
# "searchFieldJson": json.dumps(searchField), # 如果增加上这一项会要求升级宜搭存储
|
|
"instanceStatus": "RUNNING"
|
|
}
|
|
|
|
res = requests.post(api, headers=headers, json=formData)
|
|
return res.json()
|
|
def pass_on(TOKEN: str,taskId, processInstanceId, staffid):
|
|
""" 函数功能:转交审批节点 """
|
|
api = f'https://api.dingtalk.com//v1.0/yida/tasks/redirect'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": TOKEN
|
|
}
|
|
payload = {
|
|
"processInstanceId" : processInstanceId,
|
|
"byManager" : "y",
|
|
"appType" : "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken" : "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"language": "zh_CN",
|
|
"remark" : "转交(接口自动)",
|
|
"nowActionExecutorId" : staffid,
|
|
"userId" : "2268275546837446",
|
|
"taskId" : int(taskId)
|
|
}
|
|
|
|
res = requests.post(api, headers=headers, json=payload)
|
|
print('转交审批节点')
|
|
return res
|
|
|
|
def read_instances_new(token, formUuid, createFromTimeGMT, createToTimeGMT, page, n):
|
|
""" 函数功能:读取流程表单的所有数据 """
|
|
|
|
api = f'https://api.dingtalk.com/v1.0/yida/forms/instances/search'
|
|
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
|
|
formData = {
|
|
"appType": "APP_UYZ0KG6L0CCNV80GZ66O",
|
|
"systemToken": "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",
|
|
"userId": "yida_pub_account", # 超级管理员账号
|
|
"language": "zh_CN",
|
|
"formUuid": formUuid,
|
|
# "searchFieldJson": json.dumps(searchField), # 如果增加上这一项会要求升级宜搭存储
|
|
'currentPage':page,
|
|
'pageSize':n
|
|
}
|
|
|
|
res = requests.post(api, headers=headers, json=formData)
|
|
return res.json()
|
|
|
|
class NpEncoder(json.JSONEncoder):
|
|
def default(self, obj):
|
|
if isinstance(obj, np.integer):
|
|
return int(obj)
|
|
elif isinstance(obj, np.floating):
|
|
return float(obj)
|
|
elif isinstance(obj, np.ndarray):
|
|
return obj.tolist()
|
|
else:
|
|
return super(NpEncoder, self).default(obj)
|
|
|
|
""" 处理流程开始 """
|
|
TOKEN = generateToken()
|
|
FORMID2 = "FORM-J7966ZA1RTU9UG2Y7SCQRB00OXJA3JX0U2DGL0" # 修改明细表
|
|
# 10分钟时间间隔
|
|
CREATE_FROM, CREATE_TO = [timeStamp(t) for t in get_time_range_minute(100000)]
|
|
|
|
# 读取修改明细表全量数据
|
|
form_data = read_instances_V2(token=TOKEN, formUuid=FORMID2, createFromTimeGMT=CREATE_FROM, createToTimeGMT=CREATE_TO, page=1, n=100)
|
|
PAGES = form_data.get('totalCount')//100 + 1
|
|
|
|
LIST_DATA = []
|
|
""" 获取全量数据 """
|
|
for i in range(1, PAGES+1):
|
|
# form_data = read_processes_instances(token=TOKEN, formUuid=FORMID, createFromTimeGMT=CREATE_FROM, createToTimeGMT=CREATE_TO, page=i, n=100, searchField={'textField_l7if5ff9': '否'})
|
|
form_data = read_instances_new(token=TOKEN, formUuid=FORMID2, createFromTimeGMT=CREATE_FROM, createToTimeGMT=CREATE_TO, page=i, n=100)
|
|
for v in range(0,len(form_data.get('data'))):
|
|
if form_data.get('data')[v]['formData']['textField_lexootfr'] == "未处理":
|
|
formData = {'textField_lexootfr':'未处理_已失效'}
|
|
formInstanceId = form_data.get('data')[v]['formInstanceId']
|
|
update_text(TOKEN, formInstanceId, formData) # 修改明细_状态为_已处理 |