Files
2026-06-25 17:41:06 +08:00

295 lines
14 KiB
Python
Raw Permalink 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.
# app/api/wechat.py
from fastapi import APIRouter, Query, BackgroundTasks, Depends
from tortoise.expressions import Q
from app.controllers.weixin.utils import get_buyer_nick_from_group_name
from app.controllers.weixin.group import weixin_group_chat_controller
from app.controllers.weixin.customer import weixin_customer_controller
from app.controllers.weixin.user import weixin_user_controller
from app.controllers.action import action_controller
from app.schemas.weixin import WeixinUserBindInfo, WeixinOrderBindInfo, TriggerWeixinGroupChat, WeixinOrderRemark, WeixinCustomerFilter, WeixinCustomerCreate
from app.http_base import unified_resp
from app.schemas.apis import Paginate
from .base import get_weixin_user
from .base import WeixinUserDep
from app.models.msg import ActionType
from datetime import datetime, timedelta
from app.utils.event_task import event_manager, EventType
from app.core.cache import cache_if
# from app.schemas.crm import CrmBindInfoCreate, CrmBindInfoUpdate
import logging
logger = logging.getLogger(__name__)
router = APIRouter(prefix="")
# 废弃
@router.post("/list_user_join_group", summary="加载用户加入的群聊列表")
@unified_resp
async def list_user_join_group(customer: WeixinCustomerCreate, weixin_user: dict = Depends(get_weixin_user)):
print(f'list_user_join_group, customer: {customer}')
# user_join_group = await weixin_group_chat_controller.list_user_join_group(customer.xingyun_id)
user_join_group = await weixin_customer_controller.get_user_detail(customer.weixin_id)
return user_join_group
@router.get("/list_customer", summary="加载客户列表")
@unified_resp
async def list_msg(paginate: Paginate = Depends(), order: str = "-id", customer_filter: WeixinCustomerFilter = Depends(), weixin_user: dict = Depends(get_weixin_user)):
print('paginate', paginate.page, paginate.page_size)
print('customer_filter', customer_filter)
print('weixin_user', weixin_user.username, weixin_user.userid)
q = Q()
data = {}
if customer_filter.order_id is not None:
q &= Q(order_id=customer_filter.order_id)
data['order_id'] = customer_filter.order_id
if customer_filter.shop_name is not None:
q &= Q(shop_name__contains=customer_filter.shop_name)
data['shop_name'] = customer_filter.shop_name
if customer_filter.union_id is not None:
# 是或者的关系 weixin_id\xingyun_id\taobao_id\union_id
q &= (Q(weixin_id=customer_filter.union_id) | Q(xingyun_id=customer_filter.union_id) | Q(taobao_id=customer_filter.union_id) | Q(union_id=customer_filter.union_id))
data['union_id'] = customer_filter.union_id
if customer_filter.union_name is not None:
# 是或者的关系 weixin_username\xingyun_name\taobao_name
q &= (Q(weixin_name__contains=customer_filter.union_name) | Q(xingyun_name__contains=customer_filter.union_name) | Q(taobao_name__contains=customer_filter.union_name))
data['union_name'] = customer_filter.union_name
if customer_filter.xingyun_tags is not None:
q &= Q(xingyun_tags__contains={"tagName": customer_filter.xingyun_tags})
data['xingyun_tags'] = customer_filter.xingyun_tags
if customer_filter.has_order is not None:
q &= Q(order_id__isnull=not customer_filter.has_order)
data['has_order'] = customer_filter.has_order
# 打印查询条件明文
print('raw query', data)
total, user_list = await weixin_customer_controller.list(paginate.page, paginate.page_size, order=[order], search=q)
lists = []
for user in user_list:
user_info = user.dump_dict()
lists.append(user_info)
user_info['user_join_group'] = await weixin_customer_controller.get_user_detail(user.weixin_id)
return {"count": total, "lists": lists}
# 群聊入口
@router.get("/get_user_info", summary="通过群ID获取到群信息以及同步数据到本地")
@unified_resp
async def get_external_group_chat_info(userid: str):
weixin_user = await weixin_user_controller.model.filter(userid=userid).first()
return weixin_user.to_dict()
# 群聊入口
@router.get("/group/get_external_group_chat_info", summary="通过群ID获取到群信息以及同步数据到本地")
@unified_resp
async def get_external_group_chat_info(chat_id: str, background_tasks: BackgroundTasks):
group_info = await weixin_group_chat_controller.get_external_group_chat_info(chat_id)
if group_info['detect_update']:
await event_manager.publish_async(EventType.GROUP_CHAT_UPDATED, group_info, background_tasks)
return group_info
@router.get("/group/get_order_relative_user_list_by_weixin_groupid", summary="通过群ID获取订单相关用户列表")
@unified_resp
async def get_order_relative_user_list_by_weixin_groupid(chat_id: str = Query(..., description="群ID"), background_tasks: BackgroundTasks = None):
async with cache_if(f'order:chat:{chat_id}', ttl=60*3) as cache:
if cache.hit:
order_list = cache.value
if order_list:
order_list[0] = await weixin_group_chat_controller.get_user_detail_by_order(order_id=order_list[0]['ctid'])
else:
order_list = await _get_order_relative_user_list_by_weixin_groupid(chat_id, background_tasks)
cache.set(order_list)
return order_list
async def _get_order_relative_user_list_by_weixin_groupid(chat_id: str = Query(..., description="群ID"), background_tasks: BackgroundTasks = None):
group_info = await weixin_group_chat_controller.get_external_group_chat_info(chat_id)
logger.info(f'group_info: {group_info}')
if group_info['detect_update'] or True:
await event_manager.publish_async(EventType.GROUP_CHAT_UPDATED, group_info, background_tasks)
name = group_info.get('name')
logger.debug(f'群聊名称: {name} chat_id {chat_id}')
user_order_list = []
external_member_list = group_info['external_member_list']
if external_member_list:
userid_list = [member['userid'] for member in external_member_list if member.get('userid')]
logger.debug(f'userid_list: {userid_list}')
customer_list = await weixin_customer_controller.model.filter(weixin_id__in=userid_list, taobao_id__isnull=False).all()
for customer in customer_list:
buyer = customer.taobao_name or customer.taobao_id
if not buyer: continue
logger.debug(f'buyer: {buyer}')
result, order_list = await weixin_group_chat_controller.get_order_relative_user_list_by_weixin_userid(customer.weixin_id)
if not result: continue
user_order_list = order_list
break
# return await weixin_group_chat_controller.get_order_relative_user_list_by_weixin_group_name(buyer_nick)
# return await weixin_group_chat_controller.get_order_relative_user_list_by_weixin_group_buyer_id(buyer_id)
if not user_order_list:
logger.warning(f'群内成员没有订单,将根据群聊名称 {name} 来获取订单相关用户列表')
assert name, "当前群聊未命名"
buyer_nick = get_buyer_nick_from_group_name(name)
logger.debug(f'name: {name}; buyer_nick: {buyer_nick}')
assert buyer_nick, "当前群聊未命名"
user_order_list = await weixin_group_chat_controller.get_order_relative_user_list_by_weixin_group_name(buyer_nick)
if group_info['detect_update']:
try:
await action_controller.check_create_group_action_is_done(group_info, user_order_list[0]['shop_name'] if user_order_list else None)
except Exception as e:
logger.exception(f'检查创建群聊动作是否完成失败: {e}')
return user_order_list
# @router.get("/group/load_xingyun_group_info", summary="通过群ID获取订单相关用户列表")
# @unified_resp
# async def load_xingyun_group_info():
# return await weixin_group_chat_controller.load_xingyun_group_info()
@router.get("/get_user_detail_by_order", summary="通过订单ID获取订单相关用户详情")
@unified_resp
async def get_user_detail_by_order(order_id: str):
return await weixin_group_chat_controller.get_user_detail_by_order(order_id)
@router.get("/get_erp_order_log", summary="通过订单ID获取订单日志")
@unified_resp
async def get_erp_order_log(order_id: str, login_user: WeixinUserDep):
result = await weixin_group_chat_controller.get_erp_order_log(order_id)
try:
await action_controller.new_action(ActionType.VIEW_ERP_LOG, login_user, order_id=order_id)
except Exception as e:
logger.exception(e)
logger.error(f'员工操作日志记录失败')
return result
# 通过私聊入口
@router.get("/get_order_relative_user_list_by_weixin_userid", summary="通过用户ID获取订单相关用户列表")
@unified_resp
async def get_order_relative_user_list_by_weixin_userid(userid: str, background_tasks: BackgroundTasks):
result, order_list = await weixin_group_chat_controller.get_order_relative_user_list_by_weixin_userid(userid)
if not result:
await event_manager.publish_async(EventType.OPEN_PERSONAL_CHAT, {"userid": userid}, background_tasks)
return order_list
@router.post("/bind_order", summary="绑定订单")
@unified_resp
async def bind_order(bind_in: WeixinOrderBindInfo, background_tasks: BackgroundTasks, login_user: WeixinUserDep):
bind_in.userid = bind_in.userid.strip()
bind_in.order_id = bind_in.order_id.strip()
logger.info(f'【绑定订单】userid: {bind_in.userid}; order_id: {bind_in.order_id}')
old_info = await weixin_customer_controller.model.filter(weixin_id=bind_in.userid, order_id=bind_in.order_id).first()
assert not old_info, "不用为客户绑定相同订单"
result, orders = await weixin_customer_controller.bind_order(bind_in)
try:
await action_controller.new_action(ActionType.BIND_ORDER, login_user, **bind_in.model_dump(exclude_unset=True))
if orders and bind_in.remark:
orders = [{
"title": order.get("title"),
"ctid": order.get("ctid"),
"trade_no": order.get("trade_no"),
"remark": order.get("remark", ""),
} for order in orders]
need_monitor_order_list = await weixin_customer_controller.remark_order_by_order_id(remark=bind_in.remark, orders=orders)
await action_controller.new_action(ActionType.WRITE_REMARK, login_user, order_id=bind_in.order_id, remark=bind_in.remark, orders=need_monitor_order_list, done=len(need_monitor_order_list) == 0)
except Exception as e:
logger.exception(e)
logger.error(f'员工操作日志记录失败')
# 用户触发绑定时,及时同步到星云有客中
await event_manager.publish_async(EventType.BIND_ORDER_FOR_USER, orders[0] if orders else {}, background_tasks)
return result
@router.post("/remark_order", summary="为订单添加额外备注")
@unified_resp
async def remark_order(remark_in: WeixinOrderRemark, login_user: WeixinUserDep):
if not remark_in.remark:
logger.warning(f'订单备注为空,将不执行任何操作')
return False
try:
need_monitor_order_list = await weixin_customer_controller.remark_order_by_order_id(remark=remark_in.remark, order_id=remark_in.order_id)
await action_controller.new_action(ActionType.WRITE_REMARK, login_user, order_id=remark_in.order_id, remark=remark_in.remark, orders=need_monitor_order_list, done=len(need_monitor_order_list) == 0)
except Exception as e:
logger.exception(e)
logger.error(f'员工操作日志记录失败')
return bool(need_monitor_order_list)
@router.post("/bind_user", summary="用户绑定客户")
@unified_resp
async def bind_user(bind_info: WeixinUserBindInfo, login_user: WeixinUserDep):
result = await weixin_customer_controller.bind_user(bind_info=bind_info)
try:
await action_controller.new_action(ActionType.BIND_USER, login_user, **bind_info.model_dump(exclude_unset=True))
except Exception as e:
logger.exception(e)
logger.error(f'员工操作日志记录失败')
return result
@router.post("/bind_inner_user", summary="用户绑定内部公司成员(erp和企微架构不同)")
@unified_resp
async def bind_inner_user(bind_info: WeixinUserBindInfo, login_user: WeixinUserDep):
result = await weixin_user_controller.bind_user(bind_info)
try:
await action_controller.new_action(ActionType.BIND_USER, login_user, **bind_info.model_dump(exclude_unset=True))
except Exception as e:
logger.exception(e)
logger.error(f'员工操作日志记录失败')
return result
@router.get("/load_recent_user_from_xingyun", summary="加载最近N天的客户数据")
@unified_resp
async def load_user_from_xingyun(days_range: int = Query(3, description="加载最近N天的客户数据")):
now_time = datetime.now()
start_time = (now_time - timedelta(days=days_range)).replace(hour=0, minute=0, second=0, microsecond=0)
end_time = now_time + timedelta(days=1)
return await weixin_customer_controller.load_user_from_xingyun(add_time_start=start_time, add_time_end=end_time)
@router.get("/load_all_user_from_xingyun", summary="加载所有客户数据")
@unified_resp
async def load_all_user_from_xingyun(background_tasks: BackgroundTasks):
await event_manager.publish_async(EventType.SYNC_XINGYUN_CONTACT_INFO, {}, background_tasks)
return True
@router.post("/trigger_create_group_chat", summary="触发创建群聊")
@unified_resp
async def trigger_create_group_chat(group_chat: TriggerWeixinGroupChat, login_user: WeixinUserDep):
try:
await action_controller.new_action(ActionType.CREATE_GROUP, login_user, **group_chat.model_dump(exclude_unset=True))
if group_chat.order_id:
username = login_user.english_name or login_user.nickname
username = username.split('-印刷')[0]
remark = f'企微联系{username}拉群'
need_monitor_order_list = await weixin_customer_controller.remark_order_by_order_id(remark=remark, order_id=group_chat.order_id)
await action_controller.new_action(ActionType.WRITE_REMARK, login_user, order_id=group_chat.order_id, remark=remark, orders=need_monitor_order_list, done=len(need_monitor_order_list) == 0)
except Exception as e:
logger.exception(e)
logger.error(f'员工操作日志记录失败')
return True