deep-risk/backend/app/services/entity_service.py
2025-12-14 20:08:27 +08:00

243 lines
8.7 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.

"""
实体服务
获取当前用户关联的实体列表,用于风险检测
"""
from typing import List, Dict, Any, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from loguru import logger
from app.models.user import User
from app.models.streamer import StreamerInfo, McnAgency
class EntityService:
"""实体服务"""
def __init__(self, db_session: AsyncSession):
self.db_session = db_session
async def get_user_entities(
self,
entity_id: Optional[str] = None,
entity_type: Optional[str] = None
) -> List[Dict[str, Any]]:
"""
获取当前用户关联的实体列表
Args:
entity_id: 指定要检测的实体ID可选如果指定则只返回该实体
entity_type: 实体类型mcn-机构streamer-主播)
Returns:
实体列表每个实体包含entity_id, entity_type, name等
"""
# 如果指定了entity_id和entity_type只返回该实体
if entity_id and entity_type:
entity = await self._get_entity_by_id(entity_id, entity_type)
if entity:
return [entity]
return []
# 获取当前用户的默认实体
if entity_id:
entity = await self._get_entity_by_id(entity_id, entity_type)
if entity:
return [entity]
return []
return []
async def get_user_entities_by_user(
self,
user: User
) -> List[Dict[str, Any]]:
"""
根据用户对象获取关联的实体列表
Args:
user: 当前用户对象
Returns:
实体列表
"""
# 如果用户没有关联实体,返回空列表
if not user.entity_id or not user.entity_type:
logger.warning(f"用户 {user.username} 未关联任何实体")
return []
# 根据实体类型获取实体列表
if user.entity_type == "mcn":
# MCN机构用户返回该机构及其所有主播
return await self._get_mcn_entities(user.entity_id)
elif user.entity_type == "streamer":
# 主播用户,返回该主播
entity = await self._get_entity_by_id(user.entity_id, "streamer")
if entity:
return [entity]
return []
else:
logger.warning(f"未知的实体类型: {user.entity_type}")
return []
async def _get_mcn_entities(self, mcn_id: str) -> List[Dict[str, Any]]:
"""
获取MCN机构及其所有主播
Args:
mcn_id: MCN机构IDmcn_agency表的mcn_id字段
Returns:
实体列表包含MCN机构和所有主播
"""
entities = []
# 1. 获取MCN机构信息
mcn_agency = await self._get_mcn_agency_by_id(mcn_id)
if mcn_agency:
entities.append({
"entity_id": mcn_agency["mcn_id"],
"entity_type": "mcn",
"name": mcn_agency["mcn_name"],
"entity_name": mcn_agency["mcn_name"],
"unified_social_credit_code": mcn_agency.get("unified_social_credit_code"),
"tax_registration_no": mcn_agency.get("tax_registration_no"),
})
logger.info(f"找到MCN机构: {mcn_agency['mcn_name']}")
# 2. 获取该MCN下的所有主播
streamers = await self._get_streamers_by_mcn_id(mcn_id)
for streamer in streamers:
entities.append({
"entity_id": streamer["streamer_id"],
"entity_type": "streamer",
"name": streamer["streamer_name"],
"entity_name": streamer["streamer_name"],
"entity_type_detail": streamer.get("entity_type"),
"id_card_no": streamer.get("id_card_no"),
"unified_social_credit_code": streamer.get("unified_social_credit_code"),
"tax_registration_no": streamer.get("tax_registration_no"),
"mcn_agency_id": mcn_id,
"mcn_name": mcn_agency["mcn_name"] if mcn_agency else None,
})
logger.info(f"MCN机构 {mcn_id} 共有 {len(streamers)} 个主播")
return entities
async def _get_entity_by_id(
self,
entity_id: str,
entity_type: str
) -> Optional[Dict[str, Any]]:
"""
根据ID获取单个实体
Args:
entity_id: 实体ID
entity_type: 实体类型
Returns:
实体信息或None
"""
if entity_type == "mcn":
return await self._get_mcn_agency_by_id(entity_id)
elif entity_type == "streamer":
return await self._get_streamer_by_id(entity_id)
else:
logger.warning(f"未知的实体类型: {entity_type}")
return None
async def _get_mcn_agency_by_id(self, mcn_id: str) -> Optional[Dict[str, Any]]:
"""获取MCN机构信息"""
stmt = select(McnAgency).where(McnAgency.mcn_id == mcn_id)
result = await self.db_session.execute(stmt)
mcn = result.scalar_one_or_none()
if not mcn:
logger.warning(f"MCN机构不存在: {mcn_id}")
return None
return {
"mcn_id": mcn.mcn_id,
"mcn_name": mcn.mcn_name,
"unified_social_credit_code": mcn.unified_social_credit_code,
"tax_registration_no": mcn.tax_registration_no,
"legal_person_name": mcn.legal_person_name,
"legal_person_id_card": mcn.legal_person_id_card,
"registered_address": mcn.registered_address,
"actual_address": mcn.actual_address,
"bank_account_no": mcn.bank_account_no,
"bank_name": mcn.bank_name,
"contact_person": mcn.contact_person,
"contact_phone": mcn.contact_phone,
"contact_email": mcn.contact_email,
"status": mcn.status,
}
async def _get_streamer_by_id(self, streamer_id: str) -> Optional[Dict[str, Any]]:
"""获取主播信息"""
stmt = select(StreamerInfo).where(StreamerInfo.streamer_id == streamer_id)
result = await self.db_session.execute(stmt)
streamer = result.scalar_one_or_none()
if not streamer:
logger.warning(f"主播不存在: {streamer_id}")
return None
return {
"streamer_id": streamer.streamer_id,
"streamer_name": streamer.streamer_name,
"entity_type": streamer.entity_type,
"id_card_no": streamer.id_card_no,
"unified_social_credit_code": streamer.unified_social_credit_code,
"tax_registration_no": streamer.tax_registration_no,
"legal_person_name": streamer.legal_person_name,
"legal_person_id_card": streamer.legal_person_id_card,
"registered_address": streamer.registered_address,
"actual_address": streamer.actual_address,
"bank_account_no": streamer.bank_account_no,
"bank_name": streamer.bank_name,
"phone_number": streamer.phone_number,
"mcn_agency_id": streamer.mcn_agency_id,
"status": streamer.status,
}
async def _get_streamers_by_mcn_id(self, mcn_id: str) -> List[Dict[str, Any]]:
"""获取MCN机构下的所有主播"""
# 先通过mcn_id找到mcn_agency的id主键
stmt_mcn = select(McnAgency).where(McnAgency.mcn_id == mcn_id)
result_mcn = await self.db_session.execute(stmt_mcn)
mcn = result_mcn.scalar_one_or_none()
if not mcn:
return []
# 通过mcn.id查找所有主播
stmt = select(StreamerInfo).where(
StreamerInfo.mcn_agency_id == mcn.id,
StreamerInfo.status == "active"
)
result = await self.db_session.execute(stmt)
streamers = result.scalars().all()
return [
{
"streamer_id": s.streamer_id,
"streamer_name": s.streamer_name,
"entity_type": s.entity_type,
"id_card_no": s.id_card_no,
"unified_social_credit_code": s.unified_social_credit_code,
"tax_registration_no": s.tax_registration_no,
"legal_person_name": s.legal_person_name,
"legal_person_id_card": s.legal_person_id_card,
"registered_address": s.registered_address,
"actual_address": s.actual_address,
"bank_account_no": s.bank_account_no,
"bank_name": s.bank_name,
"phone_number": s.phone_number,
"status": s.status,
}
for s in streamers
]