ad-password-self-service/utils/feishu/api_approval.py

350 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals
import json
from typing import TYPE_CHECKING, Dict, List, Tuple
from utils.feishu.dt_approval import ApprovalDefinition, ApprovalForm, ApprovalInstance, ApprovalNode
from utils.feishu.dt_enum import ApprovalUploadFileType
from utils.feishu.dt_help import make_datatype
from utils.feishu.exception import LarkInvalidArguments
from utils.feishu.helper import converter_enum, to_file_like
if TYPE_CHECKING:
from utils.feishu.api import OpenLark
def _transfer_locale(locale='zh'):
return {'zh': 'zh-CN', 'en': 'en-US'}.get(str(locale).lower())
class APIApprovalMixin(object):
def get_approval_definition(self, definition_code, locale='zh'):
"""查看审批定义
:type self: OpenLark
:param definition_code: 审批定义Code需要有管理员权限然后在 https://www.feishu.cn/approval/admin/approvalList 创建
:type definition_code: str
:param locale: zh or en
:type locale: str
:return: 审批定义对象 ApprovalDefinition
:rtype: ApprovalDefinition
根据 definition_code 获取某个审批定义的详情,用于构造创建审批实例的请求。
https://open.feishu.cn/document/ukTMukTMukTM/uADNyUjLwQjM14CM0ITN
"""
url = self._gen_request_url('/approval/openapi/v2/approval/get', app='approval')
locale = {'zh': 'zh-CN', 'en': 'en-US'}.get(str(locale).lower())
body = {'approval_code': definition_code, 'locale': locale}
res = self._post(url, body, with_tenant_token=True)
data = res['data']
approval_name = data['approval_name']
form = json.loads(data['form'])
nodes = data['node_list']
definition = ApprovalDefinition(
approval_name=approval_name,
forms=[make_datatype(ApprovalForm, i) for i in form],
nodes=[make_datatype(ApprovalNode, i) for i in nodes],
)
return definition
def get_approval_instance_code_list(self, approval_code, start_time, end_time, offset=0, limit=100):
"""批量获取审批实例ID
:type self: OpenLark
:param approval_code: 审批定义code需要有管理员权限然后在 https://www.feishu.cn/approval/admin/approvalList 创建
:type approval_code: str
:param start_time: 审批实例创建时间区间13位毫秒级时间戳
:type start_time: int
:param end_time: 审批实例创建时间区间13位毫秒级时间戳
:type end_time: int
:param offset: 分页参数
:type offset: int
:param limit: 分页参数不得大于100
:type limit: int
:return: 审批实例ID数组
:rtype: list[str]
根据 approval_code 批量获取审批实例的 instance_code用于拉取租户下某个审批定义的全部审批实例。 默认以审批创建时间排序。
https://open.feishu.cn/document/ukTMukTMukTM/uQDOyUjL0gjM14CN4ITN
"""
url = self._gen_request_url('/approval/openapi/v2/instance/list', app='approval')
body = {
'approval_code': approval_code,
'start_time': start_time,
'end_time': end_time,
'offset': offset,
'limit': limit,
}
res = self._post(url, body=body, with_tenant_token=True)
data = res['data']
return data.get('instance_code_list', []) # type: List[str]
def get_approval_instance(self, instance_code, locale='zh'):
"""获取单个审批实例详情
:type self: OpenLark
:param instance_code: 审批实例 code需要有管理员权限然后在 https://www.feishu.cn/approval/admin/approvalList 创建
:type instance_code: str
:param locale zh 中文en 英文
:type locale: str
:return: 审批实例的对象 ApprovalInstance
:rtype: ApprovalInstance
根据 instance_code 获取某个审批实例的详情instance_code 由【批量获取审批实例】接口获取。
一般情况下当实例状态为1需定期重新拉取以确保获取到最新的实例详情。
https://open.feishu.cn/document/ukTMukTMukTM/uEDNyUjLxQjM14SM0ITN
"""
url = self._gen_request_url('/approval/openapi/v2/instance/get', app='approval')
body = {'instance_code': instance_code, 'locale': _transfer_locale(locale)}
res = self._post(url, body=body, with_tenant_token=True)
data = res['data']
instance = make_datatype(ApprovalInstance, data)
return instance
def create_approval(self,
definition_code,
employee_id,
department_id,
form_list,
approver_employee_id_list,
cc_employee_id_list=None,
node_approver_employee_id_list=None):
"""创建审批实例
:type self: OpenLark
:param definition_code: 审批定义 code需要有管理员权限然后在 https://www.feishu.cn/approval/admin/approvalList 创建
:type definition_code: str
:param employee_id: 租户内用户唯一 ID
:type employee_id: str
:param department_id: 部门 ID
:type department_id: str
:param form_list: 审批的表单内容
:type form_list: list[(str, Any)]
:param approver_employee_id_list: 审批人用户 ID 列表
:type approver_employee_id_list: list[str]
:param cc_employee_id_list: 抄送人用户 ID 列表
:type cc_employee_id_list: list[str]
:param node_approver_employee_id_list: 发起人自选审批人列表
:type node_approver_employee_id_list: Dict[str, list[str]]
:return: 审批实例的 instance_code
:rtype: str
创建一个审批实例,调用方需对审批定义的表单有详细了解,将按照定义的表单结构,将表单 Value 通过接口传入。
https://open.feishu.cn/document/ukTMukTMukTM/uYDO24iN4YjL2gjN
"""
form = []
for i in form_list:
if len(i) != 2:
raise LarkInvalidArguments(msg='the length of item in a form_list be 2(key and value)')
form.append({'id': i[0], 'value': i[1]})
url = self._gen_request_url('/approval/openapi/v1/instance/create', app='approval')
if not cc_employee_id_list:
cc_employee_id_list = []
if not node_approver_employee_id_list:
node_approver_employee_id_list = {}
body = {
'definition_code': definition_code,
'employee_id': employee_id,
'department_id': department_id,
'form': json.dumps(form),
'approver_employee_id_list': approver_employee_id_list,
'cc_employee_id_list': cc_employee_id_list,
'node_approver_employee_id_list': node_approver_employee_id_list,
}
res = self._post(url, body=body, with_tenant_token=True)
return res.get('data', {}).get('instance_code', '')
def subscribe_approval(self, definition_code):
"""订阅审批事件
:type self: OpenLark
:param definition_code: 审批定义Code需要有管理员权限然后在 https://www.feishu.cn/approval/admin/approvalList 创建
:type definition_code: str
:raise: LarkApprovalSubscriptionExistException 重复订阅会抛错
订阅 definition_code 后,可以收到该审批定义对应实例的事件通知。
https://open.feishu.cn/document/ukTMukTMukTM/uUTOwEjL1kDMx4SN5ATM
"""
url = self._gen_request_url('/approval/openapi/v1/subscription/subscribe', app='approval')
body = {'definition_code': definition_code}
self._post(url, body=body, with_tenant_token=True)
def unsubscribe_approval(self, definition_code):
"""取消订阅审批事件
:type self: OpenLark
:param definition_code: 审批定义Code
:type definition_code: str
取消订阅 definition_code 后,无法再收到该审批定义对应实例的事件通知。
https://open.feishu.cn/document/ukTMukTMukTM/uYTOwEjL2kDMx4iN5ATM
"""
url = self._gen_request_url('/approval/openapi/v1/subscription/unsubscribe', app='approval')
body = {'definition_code': definition_code}
self._post(url, body=body, with_tenant_token=True)
def approve_approval(self,
approval_code,
instance_code,
user_id,
task_id,
comment=None):
"""审批任务同意
:type self: OpenLark
:param approval_code: 审批定义 code
:type approval_code: str
:param instance_code: 审批实例 code
:type instance_code: str
:param user_id: 操作用户的 user_id(v3 接口的 employee_id)
:type user_id: str
:param task_id: 任务id
:type task_id: str
:param comment: 意见
:type comment: str
对于单个审批任务进行同意操作。同意后审批流程会流转到下一个审批人。
https://open.feishu.cn/document/ukTMukTMukTM/uMDNyUjLzQjM14yM0ITN
"""
url = self._gen_request_url('/approval/openapi/v2/instance/approve', app='approval')
body = {
'approval_code': approval_code,
'instance_code': instance_code,
'user_id': user_id,
'task_id': task_id,
'comment': comment,
}
self._post(url, body, with_tenant_token=True)
def reject_approval(self,
approval_code,
instance_code,
user_id,
task_id,
comment=None):
"""审批任务拒绝
:type self: OpenLark
:param approval_code: 审批定义 code
:type approval_code: str
:param instance_code: 审批实例 code
:type instance_code: str
:param user_id: 操作用户的 user_id(v3 接口的 employee_id)
:type user_id: str
:param task_id: 任务id
:type task_id: str
:param comment: 意见
:type comment: str
对于单个审批任务进行拒绝操作。拒绝后审批流程结束。
https://open.feishu.cn/document/ukTMukTMukTM/uQDNyUjL0QjM14CN0ITN
"""
url = self._gen_request_url('/approval/openapi/v2/instance/reject', app='approval')
body = {
'approval_code': approval_code,
'instance_code': instance_code,
'user_id': user_id,
'task_id': task_id,
'comment': comment,
}
self._post(url, body, with_tenant_token=True)
def transfer_approval(self,
approval_code,
instance_code,
user_id,
task_id,
transfer_user_id,
comment=None):
"""审批任务转交
:type self: OpenLark
:param approval_code: 审批定义 code
:type approval_code: str
:param instance_code: 审批实例 code
:type instance_code: str
:param user_id: 操作用户的 user_id(v3 接口的 employee_id)
:type user_id: str
:param task_id: 任务id
:type task_id: str
:param comment: 意见
:type comment: str
:param transfer_user_id: 被转交用户的 user_id(v3 接口的 employee_id)
:type transfer_user_id: str
对于单个审批任务进行转交操作。转交后审批流程流转给被转交人。
https://open.feishu.cn/document/ukTMukTMukTM/uUDNyUjL1QjM14SN0ITN?lang=zh-CN
"""
url = self._gen_request_url('/approval/openapi/v2/instance/transfer', app='approval')
body = {
'approval_code': approval_code,
'instance_code': instance_code,
'user_id': user_id,
'task_id': task_id,
'comment': comment,
'transfer_user_id': transfer_user_id,
}
self._post(url, body, with_tenant_token=True)
def cancel_approval(self, approval_code, instance_code, user_id):
"""审批实例撤销
:type self: OpenLark
:param approval_code: 审批定义 code
:type approval_code: str
:param instance_code: 审批实例 code
:param user_id: 操作用户的 user_id(v3 接口的 employee_id)
对于单个审批实例进行撤销操作。撤销后审批流程结束。
https://open.feishu.cn/document/ukTMukTMukTM/uYDNyUjL2QjM14iN0ITN?lang=zh-CN
"""
url = self._gen_request_url('/approval/openapi/v2/instance/cancel', app='approval')
body = {
'approval_code': approval_code,
'instance_code': instance_code,
'user_id': user_id,
}
self._post(url, body, with_tenant_token=True)
def upload_approval_file(self, name, filetype, content):
"""审批所需要的文件上传
:type self: OpenLark
:param name: 文件名,需包含文件扩展名,如“文件.doc
:type name: str
:param filetype: 文件类型,只能是 image 和 attachment 之一
:type filetype: ApprovalUploadFileType
:param content: 文件支持路径、bytes、BytesIO
:return: 返回的第一个是可以用于审批的 code第二个是图片或者文件的 URL
:rtype: Tuple[str, str]
"""
content = to_file_like(content)
url = self._gen_request_url('/approval/openapi/v1/file/upload', app='approval')
body = {
'name': name,
'type': converter_enum(filetype),
}
files = {'content': content}
res = self._post(url=url, body=body, files=files, with_tenant_token=True)
data = res['data']
code = data.get('code', '') # type: str
url = data.get('url', '') # type: str
return code, url