完成商家投诉模块的开发

This commit is contained in:
aaron 2025-03-20 09:10:27 +08:00
parent 313e4d5263
commit ba3e00aab6
6 changed files with 221 additions and 1 deletions

View File

@ -0,0 +1,138 @@
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from sqlalchemy import and_, desc, func
from typing import Optional, List
from app.core.response import success_response
from app.api.deps import get_db, get_current_user, get_admin_user
from app.models.merchant_complaint import MerchantComplaintDB, MerchantComplaintCreate, MerchantComplaintInfo, MerchantComplaintUpdate, ComplaintStatus
from app.models.user import UserDB
from app.models.merchant import MerchantDB
from datetime import datetime
from app.core.wecombot import WecomBot
router = APIRouter()
@router.get("/get_reason_list")
async def get_reason_list(
db: Session = Depends(get_db)
):
"""
获取投诉原因列表
"""
# 获取投诉原因列表
reason_list = [
"商家不让使用快捷买单",
"商家引导用户使用其他支付方式",
"商家存在食品安全问题",
"商家涉及违法违规行为"
]
return success_response(data={"items": reason_list}, message="投诉原因列表获取成功")
@router.post("/")
async def create_complaint(
complaint: MerchantComplaintCreate,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""
创建商家投诉
"""
try:
# 检查商家是否存在
merchant = db.query(MerchantDB).filter(MerchantDB.id == complaint.merchant_id).first()
if not merchant:
raise HTTPException(status_code=404, detail="商家不存在")
# 创建投诉记录
db_complaint = MerchantComplaintDB(
user_id=current_user.userid, # 使用当前用户ID而不是请求中的user_id
merchant_id=complaint.merchant_id,
content=complaint.content,
image_urls=complaint.image_urls,
status=ComplaintStatus.PENDING # 默认状态为等待处理
)
db.add(db_complaint)
db.commit()
db.refresh(db_complaint)
# 发送企业微信消息
await WecomBot().send_merchant_complaint(db_complaint)
return success_response(data={"id": db_complaint.id}, message="投诉提交成功")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/")
async def get_complaints(
status: Optional[ComplaintStatus] = None,
merchant_id: Optional[int] = None,
start_time: Optional[datetime] = None,
end_time: Optional[datetime] = None,
skip: int = Query(0, ge=0),
limit: int = Query(10, ge=1, le=100),
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""
获取当前用户的投诉列表
"""
# 构建查询条件
conditions = [MerchantComplaintDB.user_id == current_user.userid]
if status:
conditions.append(MerchantComplaintDB.status == status)
if merchant_id:
conditions.append(MerchantComplaintDB.merchant_id == merchant_id)
if start_time:
conditions.append(MerchantComplaintDB.create_time >= start_time)
if end_time:
conditions.append(MerchantComplaintDB.create_time <= end_time)
# 查询总数
total = db.query(func.count(MerchantComplaintDB.id)).filter(and_(*conditions)).scalar()
# 查询数据
complaints = db.query(MerchantComplaintDB).filter(and_(*conditions)).order_by(
desc(MerchantComplaintDB.create_time)
).offset(skip).limit(limit).all()
# 获取商家名称
result = []
for complaint in complaints:
complaint_info = MerchantComplaintInfo.model_validate(complaint)
complaint_info.merchant_name = complaint.merchant.name
complaint_info.user_name = complaint.user.nickname
result.append(complaint_info)
return success_response(data={
"total": total,
"items": result
})
@router.put("/{complaint_id}")
async def update_complaint_status(
complaint_id: int,
complaint_update: MerchantComplaintUpdate,
db: Session = Depends(get_db),
_: UserDB = Depends(get_admin_user) # 确保只有管理员可以修改状态
):
"""
更新投诉状态仅管理员可用
"""
# 查询投诉记录
complaint = db.query(MerchantComplaintDB).filter(MerchantComplaintDB.id == complaint_id).first()
if not complaint:
raise HTTPException(status_code=404, detail="投诉记录不存在")
# 更新状态
complaint.status = complaint_update.status
db.commit()
db.refresh(complaint)
return success_response(message="投诉状态更新成功")

View File

@ -108,6 +108,8 @@ class Settings(BaseSettings):
# 反馈需求企业微信
FEEDBACK_NEED_WECOM_BOT_WEBHOOK_URL: str = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=ccd6e8d4-4c8a-45b4-9b6b-dd4cae563176"
# 商家投诉企业微信
MERCHANT_COMPLAINT_WECOM_BOT_WEBHOOK_URL: str = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=3cd49671-0481-479b-84f0-ada09b8488df"
# DeepSeek 相关配置
DEEPSEEK_API_KEY: str = "sk-9f6b56f08796435d988cf202e37f6ee3"

View File

@ -7,6 +7,7 @@ from app.models.order import OrderStatus
from app.models.order import ShippingOrderDB
import aiohttp
from app.models.community import CommunityDB
from app.models.merchant_complaint import MerchantComplaintDB
from app.models.user import UserDB
from sqlalchemy.orm import Session
import logging
@ -171,6 +172,26 @@ class WecomBot:
except Exception as e:
logging.exception(f"发送企业微信消息失败: {str(e)}")
raise e
async def send_merchant_complaint(self, complaint: MerchantComplaintDB) -> bool:
"""
发送商家投诉通知
"""
try:
content = f"""# ‼️ 商家投诉通知
> **环境:{settings.ENV_NAME}**
**投诉信息**
> 投诉商家: {complaint.merchant.name} (ID: {complaint.merchant.id})
> 投诉用户: {complaint.user.nickname} (ID: {complaint.user.userid})
> 投诉原因: {complaint.content}
> 投诉时间: {CommonUtils.get_asia_datetime(complaint.create_time)}
"""
return await self.send_markdown(content, settings.MERCHANT_COMPLAINT_WECOM_BOT_WEBHOOK_URL)
except Exception as e:
logging.exception(f"发送企业微信消息失败: {str(e)}")
raise e
async def send_order_notification(self,db: Session, shipping_order: ShippingOrderDB, notify_type: OrderStatus = OrderStatus.CREATED) -> bool:
"""

View File

@ -1,6 +1,6 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message, bank_card, withdraw, mp, point_product, point_product_order, coupon_activity, dashboard, wecom, feedback, timeperiod, community_timeperiod, order_additional_fee, ai, community_set, community_set_mapping, community_profit_sharing, partner, health, scheduler, statistics
from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message, bank_card, withdraw, mp, point_product, point_product_order, coupon_activity, dashboard, wecom, feedback, timeperiod, community_timeperiod, order_additional_fee, ai, community_set, community_set_mapping, community_profit_sharing, partner, health, scheduler, statistics, merchant_complaint
from app.models.database import Base, engine
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
@ -98,6 +98,7 @@ app.include_router(merchant_category.router, prefix="/api/merchant-categories",
app.include_router(merchant_product.router, prefix="/api/merchant/product", tags=["商家产品"])
app.include_router(merchant_order.router, prefix="/api/merchant/order", tags=["商家订单"])
app.include_router(merchant_pay_order.router,prefix="/api/merchant-pay",tags=["商家在线买单"])
app.include_router(merchant_complaint.router, prefix="/api/merchant-complaints", tags=["商家投诉"])
app.include_router(message.router, prefix="/api/message", tags=["消息中心"])
app.include_router(upload.router, prefix="/api/upload", tags=["文件上传"])
app.include_router(config.router, prefix="/api/config", tags=["系统配置"])

View File

@ -0,0 +1,58 @@
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, JSON, Enum
from sqlalchemy.sql import func
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from .database import Base
from sqlalchemy.orm import relationship
import enum
class ComplaintStatus(str, enum.Enum):
"""投诉状态枚举"""
PENDING = "PENDING" # 等待处理
PROCESSED = "PROCESSED" # 已处理
class MerchantComplaintDB(Base):
"""商家投诉表"""
__tablename__ = "merchant_complaints"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.userid"), nullable=False) # 投诉用户ID
merchant_id = Column(Integer, ForeignKey("merchants.id"), nullable=False) # 被投诉商家ID
content = Column(Text, nullable=False) # 投诉内容
image_urls = Column(JSON, nullable=True) # 投诉图片URL列表JSON格式存储
status = Column(Enum(ComplaintStatus), default=ComplaintStatus.PENDING, nullable=False) # 投诉状态
create_time = Column(DateTime(timezone=True), server_default=func.now())
update_time = Column(DateTime(timezone=True), onupdate=func.now())
# 关联用户
user = relationship("UserDB", backref="merchant_complaints")
# 关联商家
merchant = relationship("MerchantDB", backref="merchant_complaints")
# Pydantic 模型用于API请求和响应
class MerchantComplaintCreate(BaseModel):
user_id: int = Field(..., description="投诉用户ID")
merchant_id: int = Field(..., description="被投诉商家ID")
content: str = Field(..., description="投诉内容")
image_urls: Optional[List[str]] = Field(default=None, description="投诉图片URL列表")
class MerchantComplaintUpdate(BaseModel):
status: ComplaintStatus = Field(..., description="投诉状态")
class MerchantComplaintInfo(BaseModel):
id: int
user_id: int
merchant_id: int
content: str
image_urls: Optional[List[str]] = None
status: ComplaintStatus
create_time: datetime
update_time: Optional[datetime] = None
# 额外字段用于API响应
user_name: Optional[str] = None # 投诉用户名称
merchant_name: Optional[str] = None # 被投诉商家名称
class Config:
from_attributes = True

Binary file not shown.