320 lines
13 KiB
Python
320 lines
13 KiB
Python
import requests
|
||
import logging
|
||
import json
|
||
from django.conf import settings
|
||
from asgiref.sync import async_to_sync
|
||
from channels.layers import get_channel_layer
|
||
|
||
logger = logging.getLogger('brands')
|
||
|
||
class OfferStatusService:
|
||
"""提供获取达人谈判状态的服务"""
|
||
|
||
@staticmethod
|
||
def fetch_status(creator_id, product_id):
|
||
"""
|
||
获取达人对产品的谈判状态
|
||
:param creator_id: 达人ID
|
||
:param product_id: 产品ID
|
||
:return: 状态字符串
|
||
"""
|
||
try:
|
||
url = "http://81.69.223.133:58099/api/operation/negotiations/offer_status/"
|
||
|
||
payload = {
|
||
'creator_id': str(creator_id),
|
||
'product_id': str(product_id)
|
||
}
|
||
|
||
# 记录请求详情
|
||
logger.info(f"发送状态查询请求: URL={url}, 参数={payload}")
|
||
|
||
response = requests.post(url, data=payload)
|
||
|
||
# 记录响应状态码
|
||
logger.info(f"接收状态查询响应: 状态码={response.status_code}")
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
# 记录响应内容
|
||
logger.info(f"状态查询响应内容: {data}")
|
||
if data['code'] == 200:
|
||
return data['data']['status']
|
||
else:
|
||
logger.error(f"获取谈判状态失败: {data['message']}")
|
||
return None
|
||
else:
|
||
# 记录详细错误信息
|
||
error_content = None
|
||
try:
|
||
error_content = response.text[:200] # 只取前200个字符
|
||
except:
|
||
pass
|
||
logger.error(f"请求谈判状态接口失败: {response.status_code}, 响应内容: {error_content}")
|
||
return None
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取谈判状态时发生错误: {str(e)}")
|
||
return None
|
||
|
||
@staticmethod
|
||
def update_creator_status(campaign_id, creator_id, status):
|
||
"""
|
||
更新达人的状态
|
||
:param campaign_id: 活动ID
|
||
:param creator_id: 达人ID
|
||
:param status: 新状态
|
||
:return: 是否更新成功
|
||
"""
|
||
try:
|
||
from apps.daren_detail.models import CreatorCampaign
|
||
|
||
# 更新数据库中的状态
|
||
creator_campaign = CreatorCampaign.objects.get(
|
||
campaign_id=campaign_id,
|
||
creator_id=creator_id
|
||
)
|
||
|
||
# 如果状态没有变化,则不进行更新
|
||
if creator_campaign.status == status:
|
||
return False
|
||
|
||
creator_campaign.status = status
|
||
creator_campaign.save()
|
||
logger.info(f"已更新数据库中的状态: 活动 {campaign_id}, 达人 {creator_id}, 状态 {status}")
|
||
return True
|
||
|
||
except CreatorCampaign.DoesNotExist:
|
||
logger.error(f"找不到关联记录: 活动 {campaign_id}, 达人 {creator_id}")
|
||
return False
|
||
except Exception as e:
|
||
logger.error(f"更新达人状态时发生错误: {str(e)}")
|
||
return False
|
||
|
||
@staticmethod
|
||
def get_campaign_creator_data(campaign_id, product_id=None):
|
||
"""
|
||
获取活动关联的所有达人信息
|
||
:param campaign_id: 活动ID
|
||
:param product_id: 产品ID(可选)
|
||
:return: 达人信息列表
|
||
"""
|
||
try:
|
||
from apps.daren_detail.models import CreatorCampaign, CreatorProfile
|
||
from ..models import Campaign, Product
|
||
|
||
# 查询活动信息
|
||
campaign = Campaign.objects.get(id=campaign_id)
|
||
|
||
# 获取产品信息
|
||
product_name = None
|
||
if product_id:
|
||
try:
|
||
product = Product.objects.get(id=product_id)
|
||
product_name = product.name
|
||
except Product.DoesNotExist:
|
||
logger.error(f"找不到产品: {product_id}")
|
||
product_id = None
|
||
|
||
# 如果没有指定产品ID,则使用活动关联的第一个产品
|
||
if not product_id and campaign.link_product.exists():
|
||
product = campaign.link_product.first()
|
||
product_id = str(product.id)
|
||
product_name = product.name
|
||
|
||
# 查询与活动关联的所有达人关联记录
|
||
creator_campaigns = CreatorCampaign.objects.filter(
|
||
campaign_id=campaign_id
|
||
).select_related('creator')
|
||
|
||
creator_list = []
|
||
for cc in creator_campaigns:
|
||
creator = cc.creator
|
||
|
||
# 获取最新状态
|
||
status = None
|
||
if product_id:
|
||
status = OfferStatusService.fetch_status(creator.id, product_id)
|
||
|
||
# 如果无法获取状态,则使用数据库中的状态
|
||
if not status:
|
||
status = cc.status
|
||
|
||
# 格式化粉丝数和观看量
|
||
followers_formatted = f"{int(creator.followers / 1000)}k" if creator.followers else "0"
|
||
avg_views_formatted = f"{int(creator.avg_video_views / 1000)}k" if creator.avg_video_views else "0"
|
||
|
||
# 构建响应数据
|
||
creator_data = {
|
||
"creator_name": creator.name,
|
||
"category": creator.category,
|
||
"followers": followers_formatted,
|
||
"gmv_generated": f"${creator.gmv}k" if creator.gmv else "$0",
|
||
"views_generated": avg_views_formatted,
|
||
"pricing": f"${creator.pricing}" if creator.pricing else "$0",
|
||
"status": status
|
||
}
|
||
creator_list.append(creator_data)
|
||
|
||
return creator_list
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取活动达人数据时发生错误: {str(e)}")
|
||
return []
|
||
|
||
@staticmethod
|
||
def send_status_update(campaign_id, creator_id, status, product_id=None):
|
||
"""
|
||
通过WebSocket发送状态更新
|
||
:param campaign_id: 活动ID
|
||
:param creator_id: 达人ID
|
||
:param status: 状态
|
||
:param product_id: 产品ID(可选)
|
||
"""
|
||
try:
|
||
# 先更新数据库中的状态
|
||
updated = OfferStatusService.update_creator_status(campaign_id, creator_id, status)
|
||
|
||
# 如果状态没有变化,则不发送更新
|
||
if not updated:
|
||
return
|
||
|
||
channel_layer = get_channel_layer()
|
||
|
||
# 构建消息数据
|
||
from ..models import Campaign, Product
|
||
|
||
try:
|
||
campaign = Campaign.objects.get(id=campaign_id)
|
||
|
||
# 1. 发送到产品特定的群组
|
||
if product_id:
|
||
# 获取该产品的所有达人数据
|
||
creator_list = OfferStatusService.get_campaign_creator_data(campaign_id, product_id)
|
||
|
||
# 查询产品名称
|
||
try:
|
||
product = Product.objects.get(id=product_id)
|
||
product_name = product.name
|
||
except Product.DoesNotExist:
|
||
logger.error(f"找不到产品: {product_id}")
|
||
product_name = None
|
||
|
||
# 构建产品特定的消息
|
||
product_message = {
|
||
'code': 200,
|
||
'message': '状态已更新',
|
||
'data': {
|
||
'campaign_id': str(campaign_id),
|
||
'product_id': str(product_id),
|
||
'product_name': product_name,
|
||
'creators': creator_list
|
||
}
|
||
}
|
||
|
||
# 发送到产品特定的群组
|
||
product_group_name = f'campaign_{campaign_id}_product_{product_id}'
|
||
async_to_sync(channel_layer.group_send)(
|
||
product_group_name,
|
||
{
|
||
'type': 'send_update',
|
||
'message': json.dumps(product_message)
|
||
}
|
||
)
|
||
|
||
logger.info(f"已发送状态更新到产品特定组: {product_group_name}")
|
||
|
||
# 2. 发送到活动通用群组,包含所有产品数据
|
||
# 获取所有产品
|
||
products_data = []
|
||
|
||
# 如果活动有关联产品
|
||
if campaign.link_product.exists():
|
||
for product in campaign.link_product.all():
|
||
# 获取该产品的所有达人数据
|
||
creator_list = OfferStatusService.get_campaign_creator_data(campaign_id, str(product.id))
|
||
|
||
# 构建产品数据
|
||
product_data = {
|
||
'product_id': str(product.id),
|
||
'product_name': product.name,
|
||
'creators': creator_list
|
||
}
|
||
products_data.append(product_data)
|
||
# 如果没有关联产品,仍然需要使用活动ID作为产品ID
|
||
else:
|
||
# 使用活动ID作为产品ID
|
||
fallback_product_id = str(campaign_id)
|
||
creator_list = OfferStatusService.get_campaign_creator_data(campaign_id, fallback_product_id)
|
||
|
||
# 构建产品数据
|
||
product_data = {
|
||
'product_id': fallback_product_id,
|
||
'product_name': campaign.name,
|
||
'creators': creator_list
|
||
}
|
||
products_data.append(product_data)
|
||
|
||
# 构建活动通用消息
|
||
campaign_message = {
|
||
'code': 200,
|
||
'message': '状态已更新',
|
||
'data': {
|
||
'campaign_id': str(campaign_id),
|
||
'products': products_data
|
||
}
|
||
}
|
||
|
||
# 发送到活动通用群组
|
||
campaign_group_name = f'campaign_{campaign_id}'
|
||
async_to_sync(channel_layer.group_send)(
|
||
campaign_group_name,
|
||
{
|
||
'type': 'send_update',
|
||
'message': json.dumps(campaign_message)
|
||
}
|
||
)
|
||
|
||
logger.info(f"已发送状态更新到活动通用组: {campaign_group_name}")
|
||
|
||
except Campaign.DoesNotExist:
|
||
logger.error(f"找不到活动: {campaign_id}")
|
||
except Exception as e:
|
||
logger.error(f"构建消息数据时出错: {str(e)}")
|
||
|
||
# 如果构建消息失败,发送简单的状态更新消息
|
||
simple_message = {
|
||
'code': 200,
|
||
'message': '状态已更新',
|
||
'data': {
|
||
'campaign_id': str(campaign_id),
|
||
'creator_id': str(creator_id),
|
||
'status': status
|
||
}
|
||
}
|
||
|
||
# 发送到活动通用群组
|
||
campaign_group_name = f'campaign_{campaign_id}'
|
||
async_to_sync(channel_layer.group_send)(
|
||
campaign_group_name,
|
||
{
|
||
'type': 'send_update',
|
||
'message': json.dumps(simple_message)
|
||
}
|
||
)
|
||
|
||
# 如果有产品ID,也发送到产品特定群组
|
||
if product_id:
|
||
product_group_name = f'campaign_{campaign_id}_product_{product_id}'
|
||
async_to_sync(channel_layer.group_send)(
|
||
product_group_name,
|
||
{
|
||
'type': 'send_update',
|
||
'message': json.dumps(simple_message)
|
||
}
|
||
)
|
||
|
||
logger.info(f"已发送状态更新: 活动 {campaign_id}, 产品 {product_id}, 达人 {creator_id}, 状态 {status}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"发送WebSocket更新失败: {str(e)}") |