This commit is contained in:
aaron 2025-03-07 01:02:59 +08:00
parent e6f266b5b1
commit 5ca85d9edb
4 changed files with 243 additions and 7 deletions

View File

@ -0,0 +1,178 @@
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.models.order_additional_fee import (
OrderAdditionalFeeDB,
OrderAdditionalFeeCreate,
OrderAdditionalFeeUpdate,
OrderAdditionalFeeInfo,
AdditionalFeeResult
)
from app.models.order import ShippingOrderDB, OrderStatus
from app.models.database import get_db
from app.api.deps import get_current_user, get_deliveryman_user
from app.models.user import UserDB
from app.core.response import success_response, error_response, ResponseModel
from typing import List, Optional
from datetime import datetime
import aiohttp
from app.core.config import settings
router = APIRouter()
@router.post("", response_model=ResponseModel)
async def create_additional_fee_request(
fee_request: OrderAdditionalFeeCreate,
db: Session = Depends(get_db),
deliveryman: UserDB = Depends(get_deliveryman_user)
):
"""创建加价请求(配送员)"""
# 检查订单是否存在
order = db.query(ShippingOrderDB).filter(
ShippingOrderDB.orderid == fee_request.orderid
).first()
if not order:
return error_response(code=404, message="订单不存在")
# 检查是否是该订单的配送员
if order.deliveryman_user_id != deliveryman.userid:
return error_response(code=403, message="您不是该订单的配送员")
# 检查是否已经有未处理的加价请求
existing_request = db.query(OrderAdditionalFeeDB).filter(
OrderAdditionalFeeDB.orderid == fee_request.orderid
).first()
if existing_request:
return error_response(code=400, message="该订单已有未处理的加价请求")
# 创建加价请求
db_fee_request = OrderAdditionalFeeDB(
orderid=fee_request.orderid,
order_user_id=order.userid,
deliveryman_id=deliveryman.userid,
reason=fee_request.reason,
photo_urls=fee_request.photo_urls,
additional_fee_amount=fee_request.additional_fee_amount,
result=AdditionalFeeResult.PENDING
)
db.add(db_fee_request)
try:
db.commit()
db.refresh(db_fee_request)
# TODO: 发送通知给用户
return success_response(data=OrderAdditionalFeeInfo.model_validate(db_fee_request))
except Exception as e:
db.rollback()
return error_response(code=500, message=f"创建加价请求失败: {str(e)}")
@router.get("/order/{orderid}", response_model=ResponseModel)
async def get_order_additional_fees(
orderid: str,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""获取订单的加价请求列表"""
# 检查订单是否存在
order = db.query(ShippingOrderDB).filter(
ShippingOrderDB.orderid == orderid
).first()
if not order:
return error_response(code=404, message="订单不存在")
# 检查是否是订单相关人员
if order.userid != current_user.userid and order.deliveryman_user_id != current_user.userid:
return error_response(code=403, message="您无权查看该订单的加价请求")
# 获取加价请求列表
fee_requests = db.query(OrderAdditionalFeeDB).filter(
OrderAdditionalFeeDB.orderid == orderid
).order_by(OrderAdditionalFeeDB.create_time.desc()).all()
return success_response(data=[
OrderAdditionalFeeInfo.model_validate(req) for req in fee_requests
])
@router.put("/{request_id}/accept", response_model=ResponseModel)
async def accept_additional_fee(
request_id: int,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""接受加价请求(用户)"""
# 获取加价请求
fee_request = db.query(OrderAdditionalFeeDB).filter(
OrderAdditionalFeeDB.id == request_id
).first()
if not fee_request:
return error_response(code=404, message="加价请求不存在")
# 检查是否是订单用户
if fee_request.order_user_id != current_user.userid:
return error_response(code=403, message="您无权处理该加价请求")
# 检查请求状态
if fee_request.result != AdditionalFeeResult.PENDING:
return error_response(code=400, message="该加价请求已处理")
# 更新请求状态
fee_request.result = AdditionalFeeResult.ACCEPTED
# 更新订单金额
order = db.query(ShippingOrderDB).filter(
ShippingOrderDB.orderid == fee_request.orderid
).first()
if order:
order.additional_fee_amount = float(fee_request.additional_fee_amount)
order.final_amount = float(order.final_amount) + float(fee_request.additional_fee_amount)
try:
db.commit()
# TODO: 发送通知给配送员
return success_response(message="已接受加价请求")
except Exception as e:
db.rollback()
return error_response(code=500, message=f"处理加价请求失败: {str(e)}")
# 更新加价请求
@router.put("/{request_id}", response_model=ResponseModel)
async def update_additional_fee(
request_id: int,
fee_request: OrderAdditionalFeeUpdate,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""更新加价请求"""
# 获取加价请求
fee_request = db.query(OrderAdditionalFeeDB).filter(
OrderAdditionalFeeDB.id == request_id
).first()
if not fee_request:
return error_response(code=404, message="加价请求不存在")
# 检查是否是订单用户
if fee_request.order_user_id != current_user.userid:
return error_response(code=403, message="您无权处理该加价请求")
# 更新加价请求
fee_request.reason = fee_request.reason
fee_request.photo_urls = fee_request.photo_urls
fee_request.additional_fee_amount = fee_request.additional_fee_amount
try:
db.commit()
db.refresh(fee_request)
return success_response(data=OrderAdditionalFeeInfo.model_validate(fee_request))
except Exception as e:
db.rollback()
return error_response(code=500, message=f"更新加价请求失败: {str(e)}")

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, ocr, dashboard, wecom, feedback, timeperiod, community_timeperiod
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, ocr, dashboard, wecom, feedback, timeperiod, community_timeperiod, order_additional_fee
from app.models.database import Base, engine
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
@ -61,8 +61,11 @@ app.include_router(account.router, prefix="/api/account", tags=["账户"])
app.include_router(address.router, prefix="/api/address", tags=["配送地址"])
app.include_router(community.router, prefix="/api/community", tags=["社区"])
app.include_router(community_building.router, prefix="/api/community/building", tags=["社区楼栋"])
app.include_router(timeperiod.router, prefix="/api/time-periods", tags=["配送时段"])
app.include_router(community_timeperiod.router, prefix="/api/community-time-periods", tags=["社区配送时段"])
app.include_router(station.router, prefix="/api/station", tags=["驿站"])
app.include_router(order.router, prefix="/api/order", tags=["订单"])
app.include_router(order_additional_fee.router, prefix="/api/order-additional-fee", tags=["订单加价"])
app.include_router(coupon.router, prefix="/api/coupon", tags=["抵扣券"])
app.include_router(coupon_activity.router, prefix="/api/coupon-activities", tags=["抵扣券活动"])
app.include_router(merchant.router, prefix="/api/merchant", tags=["商家"])
@ -76,8 +79,7 @@ app.include_router(config.router, prefix="/api/config", tags=["系统配置"])
app.include_router(log.router, prefix="/api/logs", tags=["系统日志"])
app.include_router(ocr.router, prefix="/api/ai/ocr", tags=["图像识别"])
app.include_router(feedback.router, prefix="/api/feedback", tags=["反馈"])
app.include_router(timeperiod.router, prefix="/api/time-periods", tags=["配送时段"])
app.include_router(community_timeperiod.router, prefix="/api/community-time-periods", tags=["社区配送时段"])
@app.get("/")
async def root():

View File

@ -71,6 +71,7 @@ class ShippingOrderDB(Base):
original_amount = Column(Float, nullable=False)
coupon_discount_amount = Column(Float, default=0)
point_discount_amount = Column(Float, default=0)
additional_fee_amount = Column(Float, default=0)
coupon_id = Column(Integer, ForeignKey("user_coupons.id"), nullable=True)
final_amount = Column(Float, nullable=False)
status = Column(Enum(OrderStatus), nullable=False, default=OrderStatus.CREATED)
@ -161,11 +162,12 @@ class OrderInfo(BaseModel):
pickup_images_count: int
package_count: int
pickup_code_count: int
original_amount: float
coupon_discount_amount: float
original_amount: float = 0
coupon_discount_amount: float = 0
point_discount_amount: float = 0
coupon_id: Optional[int]
final_amount: float
additional_fee_amount: float = 0
coupon_id: Optional[int] = None
final_amount: float = 0
status: OrderStatus
complete_images: Optional[str] = None
optimized_complete_images: Optional[List[str]] = None

View File

@ -0,0 +1,54 @@
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Enum, DECIMAL, JSON
from sqlalchemy.sql import func
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from .database import Base
import enum
class AdditionalFeeResult(str, enum.Enum):
PENDING = "PENDING" # 待处理
ACCEPTED = "ACCEPTED" # 已接受
REJECTED = "REJECTED" # 已拒绝
class OrderAdditionalFeeDB(Base):
__tablename__ = "order_additional_fees"
id = Column(Integer, primary_key=True, autoincrement=True)
orderid = Column(String(32), ForeignKey("shipping_orders.orderid"), nullable=False, index=True)
order_user_id = Column(Integer, ForeignKey("users.userid"), nullable=False)
deliveryman_id = Column(Integer, ForeignKey("users.userid"), nullable=False)
reason = Column(String(200), nullable=False)
photo_urls = Column(JSON, nullable=True) # 存储照片URL的JSON数组
additional_fee_amount = Column(DECIMAL(10, 2), nullable=False)
result = Column(Enum(AdditionalFeeResult), nullable=False, default=AdditionalFeeResult.PENDING)
create_time = Column(DateTime(timezone=True), server_default=func.now())
update_time = Column(DateTime(timezone=True), onupdate=func.now())
# Pydantic 模型
class OrderAdditionalFeeCreate(BaseModel):
orderid: str
reason: str = Field(..., max_length=200)
photo_urls: Optional[List[str]] = None
additional_fee_amount: float = Field(..., gt=0)
class OrderAdditionalFeeUpdate(BaseModel):
id: int
reason: str
photo_urls: Optional[List[str]]
additional_fee_amount: float
class OrderAdditionalFeeInfo(BaseModel):
id: int
orderid: str
order_user_id: int
deliveryman_id: int
reason: str
photo_urls: Optional[List[str]]
additional_fee_amount: float
result: AdditionalFeeResult
create_time: datetime
update_time: Optional[datetime] = None
class Config:
from_attributes = True