202 lines
7.9 KiB
Python
202 lines
7.9 KiB
Python
|
|
from app.core.crud import CRUDBase
|
|
from app.schemas.weixin import (
|
|
WeixinUserCreate,
|
|
WeixinUserUpdate,
|
|
)
|
|
|
|
from app.models.weixin import WeixinUser
|
|
from app.schemas.weixin import WeixinUserBindInfo
|
|
|
|
from some_sdk.services.binder import feishu_client, xy_client
|
|
from some_sdk.feishu_sdk.biz.doc import search_file_record
|
|
from some_sdk.xingyun_sdk.apis.channel import list_channel_group, list_channel_group_user_list, set_online_staff
|
|
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
from datetime import datetime
|
|
|
|
def split_generator(iterable, chunk_size=50):
|
|
"""
|
|
将可迭代对象拆分为多个子列表
|
|
"""
|
|
chunk = []
|
|
for item in iterable:
|
|
chunk.append(item)
|
|
if len(chunk) == chunk_size:
|
|
yield chunk
|
|
chunk = []
|
|
if chunk:
|
|
yield chunk
|
|
|
|
class WeixinUserController(CRUDBase[WeixinUser, WeixinUserCreate, WeixinUserUpdate]):
|
|
def __init__(self):
|
|
super().__init__(model=WeixinUser)
|
|
|
|
async def update_from_group(self, internal_members: list[dict]):
|
|
# 同步更新数据库
|
|
member_dict = {}
|
|
for member in internal_members:
|
|
member = member.copy()
|
|
userid = member.get('userid', None)
|
|
member['alias'] = member.pop('name', None)
|
|
member_dict[userid] = member
|
|
|
|
member_list = await self.model.filter(userid__in=member_dict.keys())
|
|
|
|
update_list = []
|
|
update_fileds = ['alias', 'role', 'erp_id', 'erp_name']
|
|
|
|
history = {}
|
|
for member in member_list:
|
|
member_info = member_dict.pop(member.userid, history.get(member.userid, {}))
|
|
if member.role in ['owner', 'admin', 'follower']:
|
|
continue
|
|
if not member_info: continue
|
|
history[member.userid] = member_info
|
|
|
|
updated = {}
|
|
for field in update_fileds:
|
|
old_value = getattr(member, field)
|
|
if field not in member_info:
|
|
continue
|
|
value = member_info.get(field)
|
|
if old_value != value:
|
|
setattr(member, field, value)
|
|
updated[f'{field}:{str(old_value)}'] = value
|
|
if updated:
|
|
logger.info(f'用户 {member.userid} 更新关系为 {updated}')
|
|
update_list.append(member)
|
|
if update_list:
|
|
await self.model.bulk_update(update_list, fields=update_fileds)
|
|
|
|
# 新增用户
|
|
create_list = []
|
|
for userid, member_info in member_dict.items():
|
|
create_list.append(WeixinUser(
|
|
**member_info,
|
|
name=member_info.get('alias'),
|
|
))
|
|
if create_list:
|
|
await self.model.bulk_create(create_list)
|
|
|
|
return {
|
|
'update_count': len(update_list),
|
|
'create_count': len(create_list),
|
|
}
|
|
|
|
|
|
async def bind_user(self, user_in: WeixinUserBindInfo):
|
|
if not user_in.userid:
|
|
raise ValueError("用户ID不能为空")
|
|
if user_in.erp_id == 0:
|
|
del user_in.erp_id
|
|
|
|
user = await self.model.filter(userid=user_in.userid).first()
|
|
if not user:
|
|
await self.create({**user_in.model_dump(exclude_unset=True), 'name': user_in.username})
|
|
return {}
|
|
await self.model.filter(userid=user_in.userid).update(**user_in.model_dump(exclude_unset=True))
|
|
|
|
async def set_user_online(self, class_type: str, date: datetime):
|
|
daysTimestamp = lambda nowStamp, days: nowStamp + days * 24 * 60 * 60 * 1000
|
|
formatDate = lambda ts: datetime.fromtimestamp(ts / 1000).strftime('%Y-%m-%d')
|
|
|
|
today = int(date.timestamp() * 1000)
|
|
logger.info(f'设置 {formatDate(today)} 班次为 {class_type} 的员工为在线状态')
|
|
yestoday = daysTimestamp(today, -1)
|
|
tomorrow = daysTimestamp(today, 1)
|
|
|
|
# 查询日期为 yestoday 到 后天 之间的所有记录
|
|
resp = search_file_record(
|
|
feishu_client,
|
|
app_token="V4qebMG2kamCWMslJmdcQMbtngW",
|
|
table_id="tblKgjc3F2jZ2inC",
|
|
filter={
|
|
"conjunction": "and",
|
|
"conditions": [{
|
|
"field_name": "日期",
|
|
"operator": "isGreater",
|
|
"value": ["ExactDate", yestoday]
|
|
},{
|
|
"field_name": "日期",
|
|
"operator": "isLess",
|
|
"value": ["ExactDate", daysTimestamp(today, 2)]
|
|
}]
|
|
},
|
|
)
|
|
|
|
set_result = {}
|
|
current_class = (class_type, today)
|
|
next_class = ('早班', tomorrow) if class_type == '晚班' else ('晚班', today)
|
|
|
|
current_class_mapping = {}
|
|
next_class_mapping = {}
|
|
async for data in resp:
|
|
user = data.get('data', {})
|
|
user_online = ((user.get('班次') or '')[:2], user.get('日期', ''))
|
|
# logger.info(f'用户{user.get("接量成员", "")} 在线时间为{user_online} 当前班次为{current_class} 下一班次为{next_class}')
|
|
class_group = user.get('组别', '')
|
|
class_mapping = None
|
|
# 当前班次
|
|
if user_online == current_class:
|
|
class_mapping = current_class_mapping
|
|
set_result[class_group] = {"接量成员": user.get('接量成员', '')}
|
|
# 下一班次
|
|
elif user_online == next_class:
|
|
class_mapping = next_class_mapping
|
|
if class_mapping is None:
|
|
continue
|
|
|
|
if user.get('id', ''):
|
|
class_mapping.setdefault(class_group, [])
|
|
class_mapping[class_group].append(user.get('id', ''))
|
|
|
|
assert current_class_mapping, f"根据日期{current_class[1]} {formatDate(current_class[1])}没有找到班次为{class_type}的员工"
|
|
logger.info(f'根据日期{current_class[1]} {formatDate(current_class[1])} 找到班次为{class_type}的员工: {current_class_mapping} {set_result}')
|
|
if next_class_mapping:
|
|
logger.info(f'根据日期{next_class[1]} {formatDate(next_class[1])} 找到班次为{next_class[0]}的员工: {next_class_mapping}')
|
|
|
|
group_list = list_channel_group(xy_client)
|
|
async for group in group_list:
|
|
title = group.get("title", "")
|
|
if title not in current_class_mapping:
|
|
continue
|
|
|
|
set_result[title] = set_result.get(title) or {}
|
|
try:
|
|
user_list = list_channel_group_user_list(xy_client, groupId=group.get("id", ""))
|
|
|
|
huomaList = []
|
|
async for user in user_list:
|
|
huomaList.append(user.get('id'))
|
|
|
|
if not huomaList:
|
|
logger.error(f'组 {title} {group.get("id", "")} 中没有员工')
|
|
continue
|
|
|
|
is_faild, is_success = [], []
|
|
# 按照50个一组设置在线状态
|
|
for i in range(0, len(huomaList), 50):
|
|
result = await set_online_staff(xy_client, allDayUserIds=','.join(current_class_mapping[title]), huomaList=huomaList[i:i+50])
|
|
|
|
is_faild += list(filter(lambda x: x.get('errorMsg', ''), result.get('data', [])))
|
|
is_success += list(filter(lambda x: x.get('success', True), result.get('data', [])))
|
|
|
|
is_faild = set(is_faild)
|
|
if is_faild: logger.error(f'设置失败的员工: {is_faild}')
|
|
else: logger.info(f'全部员工设置成功')
|
|
|
|
set_result[title] = {
|
|
'success': len(is_success),
|
|
'fail': len(is_faild),
|
|
**set_result[title]
|
|
}
|
|
except Exception as e:
|
|
logger.exception(f'设置群 {group.get("id", "")} 中员工 {huomaList} 为在线状态失败: {e}')
|
|
|
|
return set_result, next_class_mapping
|
|
|
|
weixin_user_controller = WeixinUserController()
|