update
This commit is contained in:
parent
28922e4cbf
commit
466660d772
@ -13,7 +13,8 @@ from app.models.order import (
|
|||||||
OrderStatus,
|
OrderStatus,
|
||||||
OrderCancel,
|
OrderCancel,
|
||||||
OrderComplete,
|
OrderComplete,
|
||||||
OrderPriceResult
|
OrderPriceResult,
|
||||||
|
RefundOrderAmountRequest
|
||||||
)
|
)
|
||||||
from app.models.order_additional_fee import OrderAdditionalFeeDB, OrderAdditionalFeeInfo, AdditionalFeeResult
|
from app.models.order_additional_fee import OrderAdditionalFeeDB, OrderAdditionalFeeInfo, AdditionalFeeResult
|
||||||
from app.models.database import get_db
|
from app.models.database import get_db
|
||||||
@ -1573,6 +1574,60 @@ async def get_orders(
|
|||||||
return error_response(code=500, message=f"获取订单列表失败: {str(e)}")
|
return error_response(code=500, message=f"获取订单列表失败: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/admin/refund_order_amount", response_model=ResponseModel)
|
||||||
|
async def refund_order_amount(
|
||||||
|
request: RefundOrderAmountRequest,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
admin_user: UserDB = Depends(get_admin_user)
|
||||||
|
):
|
||||||
|
"""减少订单金额"""
|
||||||
|
try:
|
||||||
|
order = db.query(ShippingOrderDB).filter(ShippingOrderDB.orderid == request.order_id).first()
|
||||||
|
if not order:
|
||||||
|
return error_response(code=404, message="订单不存在")
|
||||||
|
|
||||||
|
# 检查退款金额是否大于订单支付金额
|
||||||
|
if request.amount > order.final_amount:
|
||||||
|
return error_response(code=400, message="退款金额不能大于订单金额")
|
||||||
|
|
||||||
|
order.refund_amount = request.amount
|
||||||
|
order.refund_reason = request.reason
|
||||||
|
order.refund_user_id = admin_user.userid
|
||||||
|
|
||||||
|
order.final_amount -= request.amount
|
||||||
|
|
||||||
|
# 如果订单已经完成,则扣减配送员收益
|
||||||
|
order.delivery_share = calculate_delivery_share(order, db)
|
||||||
|
if order.status == OrderStatus.COMPLETED:
|
||||||
|
# 扣减配送员收益
|
||||||
|
sharing = db.query(CommunityProfitSharing).filter(
|
||||||
|
CommunityProfitSharing.community_id == order.address_community_id
|
||||||
|
).first()
|
||||||
|
if sharing:
|
||||||
|
reduct_share = -round(request.amount * (float(sharing.delivery_rate) / 100.0), 2)
|
||||||
|
manager = AccountManager(db)
|
||||||
|
manager.change_balance(
|
||||||
|
order.deliveryman_user_id,
|
||||||
|
reduct_share,
|
||||||
|
f"配送订单退款",
|
||||||
|
order.orderid
|
||||||
|
)
|
||||||
|
|
||||||
|
wechat = WeChatClient()
|
||||||
|
await wechat.apply_refund(
|
||||||
|
order_id=order.orderid,
|
||||||
|
total_amount=int(float(request.amount) * 100) if not settings.DEBUG else 1, # 转换为分
|
||||||
|
reason="后台退款"
|
||||||
|
)
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
return success_response(message="减少订单金额成功")
|
||||||
|
except Exception as e:
|
||||||
|
db.rollback()
|
||||||
|
logging.exception(f"减少订单金额失败: {str(e)}")
|
||||||
|
return error_response(code=500, message=f"减少订单金额失败: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
@router.get("/admin/list", response_model=ResponseModel)
|
@router.get("/admin/list", response_model=ResponseModel)
|
||||||
async def get_admin_orders(
|
async def get_admin_orders(
|
||||||
status: Optional[OrderStatus] = None,
|
status: Optional[OrderStatus] = None,
|
||||||
@ -1654,6 +1709,9 @@ async def get_admin_orders(
|
|||||||
"complete_images": order.optimized_complete_images,
|
"complete_images": order.optimized_complete_images,
|
||||||
"completed_time": order.completed_time,
|
"completed_time": order.completed_time,
|
||||||
"final_amount": order.final_amount,
|
"final_amount": order.final_amount,
|
||||||
|
"refund_amount": order.refund_amount,
|
||||||
|
"refund_reason": order.refund_reason,
|
||||||
|
"refund_user_id": order.refund_user_id,
|
||||||
"packages": package_list,
|
"packages": package_list,
|
||||||
"sub_orders": [PointProductOrderInfo.model_validate(sub_order) for sub_order in sub_orders],
|
"sub_orders": [PointProductOrderInfo.model_validate(sub_order) for sub_order in sub_orders],
|
||||||
"address": {
|
"address": {
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import logging
|
|||||||
from app.core.security import get_password_hash
|
from app.core.security import get_password_hash
|
||||||
from app.models.order_additional_fee import OrderAdditionalFeeDB, AdditionalFeeResult
|
from app.models.order_additional_fee import OrderAdditionalFeeDB, AdditionalFeeResult
|
||||||
from app.api.endpoints.order import calculate_delivery_share
|
from app.api.endpoints.order import calculate_delivery_share
|
||||||
from app.models.wechat_payment import WechatPaymentRecordDB
|
from app.models.wechat_payment import WechatPaymentRecordDB, WechatRefundRecordDB
|
||||||
from app.core.wecombot import WecomBot
|
from app.core.wecombot import WecomBot
|
||||||
from app.models.order import OrderInfo
|
from app.models.order import OrderInfo
|
||||||
|
|
||||||
@ -400,14 +400,52 @@ async def refund_notify(
|
|||||||
|
|
||||||
# 获取退款信息
|
# 获取退款信息
|
||||||
out_trade_no = data.get("out_trade_no") # 订单号
|
out_trade_no = data.get("out_trade_no") # 订单号
|
||||||
|
out_refund_no = data.get("out_refund_no") # 退款单号
|
||||||
|
refund_id = data.get("refund_id") # 微信退款单号
|
||||||
|
transaction_id = data.get("transaction_id") # 微信支付交易号
|
||||||
status = data.get("refund_status")
|
status = data.get("refund_status")
|
||||||
success_time = data.get("success_time")
|
success_time = data.get("success_time")
|
||||||
|
refund_amount = data.get("amount", {}).get("refund")
|
||||||
|
total_amount = data.get("amount", {}).get("total")
|
||||||
|
user_received_account = data.get("user_received_account")
|
||||||
|
refund_reason = "退款" # 默认退款原因
|
||||||
|
|
||||||
|
# 保存退款记录数据
|
||||||
|
refund_record = WechatRefundRecordDB(
|
||||||
|
out_trade_no=out_trade_no,
|
||||||
|
out_refund_no=out_refund_no,
|
||||||
|
refund_id=refund_id,
|
||||||
|
transaction_id=transaction_id,
|
||||||
|
refund_status=status,
|
||||||
|
success_time=datetime.fromisoformat(success_time.replace('Z', '+00:00')) if success_time else None,
|
||||||
|
refund_amount=float(refund_amount) / 100 if refund_amount else 0,
|
||||||
|
total_amount=float(total_amount) / 100 if total_amount else 0,
|
||||||
|
user_received_account=user_received_account,
|
||||||
|
refund_reason=refund_reason,
|
||||||
|
raw_data=data
|
||||||
|
)
|
||||||
|
db.add(refund_record)
|
||||||
|
|
||||||
if not all([out_trade_no, status]) or status != "SUCCESS":
|
if not all([out_trade_no, status]) or status != "SUCCESS":
|
||||||
return error_response(code=400, message="缺少必要的退款信息或退款未成功")
|
return error_response(code=400, message="缺少必要的退款信息或退款未成功")
|
||||||
|
|
||||||
# 根据订单类型处理退款
|
# 根据订单类型处理退款
|
||||||
if out_trade_no.startswith('M'): # 商家商品订单
|
if out_trade_no.startswith('D'): # 配送订单
|
||||||
|
order = db.query(ShippingOrderDB).filter(
|
||||||
|
ShippingOrderDB.orderid == out_trade_no
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if not order:
|
||||||
|
return error_response(code=404, message="订单不存在或状态不正确")
|
||||||
|
|
||||||
|
# 更新退款相关字段
|
||||||
|
if refund_amount:
|
||||||
|
order.refund_amount = refund_amount
|
||||||
|
|
||||||
|
# 记录退款时间
|
||||||
|
order.refund_time = datetime.fromisoformat(success_time.replace('Z', '+00:00'))
|
||||||
|
|
||||||
|
elif out_trade_no.startswith('M'): # 商家商品订单
|
||||||
order = db.query(MerchantOrderDB).filter(
|
order = db.query(MerchantOrderDB).filter(
|
||||||
MerchantOrderDB.order_id == out_trade_no,
|
MerchantOrderDB.order_id == out_trade_no,
|
||||||
MerchantOrderDB.status == MerchantOrderStatus.REFUNDING
|
MerchantOrderDB.status == MerchantOrderStatus.REFUNDING
|
||||||
@ -418,7 +456,7 @@ async def refund_notify(
|
|||||||
|
|
||||||
# 更新订单状态
|
# 更新订单状态
|
||||||
order.status = MerchantOrderStatus.CANCELLED
|
order.status = MerchantOrderStatus.CANCELLED
|
||||||
order.refund_transaction_id = data.get("transaction_id")
|
order.refund_transaction_id = transaction_id
|
||||||
order.refund_time = datetime.fromisoformat(success_time.replace('Z', '+00:00'))
|
order.refund_time = datetime.fromisoformat(success_time.replace('Z', '+00:00'))
|
||||||
|
|
||||||
elif out_trade_no.startswith('P'): # 商家在线买单
|
elif out_trade_no.startswith('P'): # 商家在线买单
|
||||||
|
|||||||
@ -94,6 +94,12 @@ class ShippingOrderDB(Base):
|
|||||||
pay_time = Column(DateTime(timezone=True)) # 支付时间
|
pay_time = Column(DateTime(timezone=True)) # 支付时间
|
||||||
transaction_id = Column(String(64)) # 微信支付交易号
|
transaction_id = Column(String(64)) # 微信支付交易号
|
||||||
|
|
||||||
|
# 退款相关字段
|
||||||
|
refund_amount = Column(Float, default=0) # 退款金额
|
||||||
|
refund_reason = Column(String(200), nullable=True) # 退款原因
|
||||||
|
refund_user_id = Column(Integer, ForeignKey("users.userid"), nullable=True) # 退款操作人
|
||||||
|
refund_time = Column(DateTime(timezone=True), nullable=True) # 退款时间
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def optimized_complete_images(self):
|
def optimized_complete_images(self):
|
||||||
if self.complete_images:
|
if self.complete_images:
|
||||||
@ -196,11 +202,11 @@ class OrderInfo(BaseModel):
|
|||||||
completed_time: Optional[datetime] = None
|
completed_time: Optional[datetime] = None
|
||||||
is_first_order: bool
|
is_first_order: bool
|
||||||
|
|
||||||
# def __init__(self, **data):
|
# 退款相关字段
|
||||||
# super().__init__(**data)
|
refund_amount: float = 0
|
||||||
# # 将逗号分隔的图片URL字符串转换为列表
|
refund_reason: Optional[str] = None
|
||||||
# if self.complete_images and isinstance(self.complete_images, str):
|
refund_user_id: Optional[int] = None
|
||||||
# self.complete_images = self.complete_images.split(",")
|
refund_time: Optional[datetime] = None
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
@ -242,3 +248,8 @@ class OrderPriceResult(BaseModel):
|
|||||||
used_coupon_id: Optional[int] = None # 使用的优惠券ID
|
used_coupon_id: Optional[int] = None # 使用的优惠券ID
|
||||||
used_points: Optional[int] = None # 使用的积分数
|
used_points: Optional[int] = None # 使用的积分数
|
||||||
price_detail_text: Optional[str] = None # 价格详情文本
|
price_detail_text: Optional[str] = None # 价格详情文本
|
||||||
|
|
||||||
|
class RefundOrderAmountRequest(BaseModel):
|
||||||
|
order_id: str
|
||||||
|
amount: float
|
||||||
|
reason: str
|
||||||
@ -48,3 +48,44 @@ class WechatPaymentRecordInfo(BaseModel):
|
|||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
||||||
|
class WechatRefundRecordDB(Base):
|
||||||
|
"""微信退款记录表"""
|
||||||
|
__tablename__ = "wechat_refund_records"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
out_trade_no = Column(String(32), nullable=False, index=True, comment='商户订单号')
|
||||||
|
out_refund_no = Column(String(64), nullable=False, index=True, comment='商户退款单号')
|
||||||
|
refund_id = Column(String(64), index=True, comment='微信退款单号')
|
||||||
|
transaction_id = Column(String(64), index=True, comment='微信支付交易号')
|
||||||
|
refund_status = Column(String(32), comment='退款状态')
|
||||||
|
success_time = Column(DateTime(timezone=True), comment='退款成功时间')
|
||||||
|
refund_amount = Column(DECIMAL(10, 2), comment='退款金额')
|
||||||
|
total_amount = Column(DECIMAL(10, 2), comment='订单总金额')
|
||||||
|
user_received_account = Column(String(256), comment='退款入账账户')
|
||||||
|
currency = Column(String(16), default='CNY', comment='货币类型')
|
||||||
|
refund_reason = Column(String(256), comment='退款原因')
|
||||||
|
raw_data = Column(JSON, comment='原始返回数据')
|
||||||
|
create_time = Column(DateTime(timezone=True), server_default=func.now(), comment='创建时间')
|
||||||
|
update_time = Column(DateTime(timezone=True), onupdate=func.now(), comment='更新时间')
|
||||||
|
|
||||||
|
# Pydantic 模型
|
||||||
|
class WechatRefundRecordInfo(BaseModel):
|
||||||
|
id: int
|
||||||
|
out_trade_no: str
|
||||||
|
out_refund_no: str
|
||||||
|
refund_id: Optional[str] = None
|
||||||
|
transaction_id: Optional[str] = None
|
||||||
|
refund_status: Optional[str] = None
|
||||||
|
success_time: Optional[datetime] = None
|
||||||
|
refund_amount: Optional[float] = None
|
||||||
|
total_amount: Optional[float] = None
|
||||||
|
user_received_account: Optional[str] = None
|
||||||
|
currency: str = 'CNY'
|
||||||
|
refund_reason: Optional[str] = None
|
||||||
|
raw_data: Optional[Dict[str, Any]] = None
|
||||||
|
create_time: datetime
|
||||||
|
update_time: Optional[datetime] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
@ -176,4 +176,13 @@ ADD UNIQUE INDEX uix_fee_order_id (fee_order_id);
|
|||||||
ALTER TABLE order_additional_fees
|
ALTER TABLE order_additional_fees
|
||||||
ADD COLUMN transaction_id VARCHAR(64) NULL COMMENT '微信支付交易号';
|
ADD COLUMN transaction_id VARCHAR(64) NULL COMMENT '微信支付交易号';
|
||||||
|
|
||||||
|
--====FINISH 4.5====
|
||||||
|
|
||||||
|
-- 为 shipping_orders 表添加 refund_amount 等字段
|
||||||
|
ALTER TABLE shipping_orders
|
||||||
|
ADD COLUMN refund_amount FLOAT DEFAULT 0,
|
||||||
|
ADD COLUMN refund_reason VARCHAR(200),
|
||||||
|
ADD COLUMN refund_user_id INT,
|
||||||
|
ADD CONSTRAINT fk_refund_user_id FOREIGN KEY (refund_user_id) REFERENCES users(userid);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
jobs.sqlite
BIN
jobs.sqlite
Binary file not shown.
Loading…
Reference in New Issue
Block a user