From ba3e00aab6a6eb6b1137b9ecaa8dbd8f068e9c2c Mon Sep 17 00:00:00 2001 From: aaron <> Date: Thu, 20 Mar 2025 09:10:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=95=86=E5=AE=B6=E6=8A=95?= =?UTF-8?q?=E8=AF=89=E6=A8=A1=E5=9D=97=E7=9A=84=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/endpoints/merchant_complaint.py | 138 ++++++++++++++++++++++++ app/core/config.py | 2 + app/core/wecombot.py | 21 ++++ app/main.py | 3 +- app/models/merchant_complaint.py | 58 ++++++++++ jobs.sqlite | Bin 24576 -> 24576 bytes 6 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 app/api/endpoints/merchant_complaint.py create mode 100644 app/models/merchant_complaint.py diff --git a/app/api/endpoints/merchant_complaint.py b/app/api/endpoints/merchant_complaint.py new file mode 100644 index 0000000..25a9fc2 --- /dev/null +++ b/app/api/endpoints/merchant_complaint.py @@ -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="投诉状态更新成功") \ No newline at end of file diff --git a/app/core/config.py b/app/core/config.py index a2f159f..81fe69f 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -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" diff --git a/app/core/wecombot.py b/app/core/wecombot.py index 3100f15..4e767f0 100644 --- a/app/core/wecombot.py +++ b/app/core/wecombot.py @@ -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: """ diff --git a/app/main.py b/app/main.py index 1abb6ef..a65996a 100644 --- a/app/main.py +++ b/app/main.py @@ -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=["系统配置"]) diff --git a/app/models/merchant_complaint.py b/app/models/merchant_complaint.py new file mode 100644 index 0000000..f988cee --- /dev/null +++ b/app/models/merchant_complaint.py @@ -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 \ No newline at end of file diff --git a/jobs.sqlite b/jobs.sqlite index fa2c6601823b7fe52b2ba6bc3a36790fd53f0c0d..37ab9d5caaa567c1c769a1604381561876d64cf1 100644 GIT binary patch delta 94 zcmZoTz}Rqrae_2s_e2?I#_o*?pT*ekICV6zPSu_4=q|IlO#B-&vnYeyDfEt-Om{}Opfr>W&w`WuU0C4gmt^fc4