first commit

This commit is contained in:
2026-06-25 17:41:06 +08:00
commit b2f23a933b
370 changed files with 30526 additions and 0 deletions
+294
View File
@@ -0,0 +1,294 @@
# 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