fix: 添加用户取消订单 + 管理员手动退款端点

This commit is contained in:
2026-05-25 13:09:54 +08:00
parent 5f3b919e92
commit 72cbb8ff28
5 changed files with 162 additions and 2 deletions

114
src/db.rs
View File

@@ -972,3 +972,117 @@ pub async fn admin_force_confirm_order(
Ok(new_expires)
}
/// 用户主动取消待支付订单
pub async fn cancel_payment_order(
pool: &PgPool,
order_no: &str,
user_id: i32,
) -> Result<(), AppError> {
// 检查订单有效且属于该用户
let row = sqlx::query_as::<_, (i32, String)>(
r#"SELECT user_id, status FROM payment_orders WHERE order_no = $1"#,
)
.bind(order_no)
.fetch_optional(pool)
.await
.map_err(|e| AppError::Database(format!("查询订单失败: {}", e)))?;
let (order_user_id, status) = match row {
Some(r) => r,
None => return Err(AppError::NotFound("订单不存在".to_string())),
};
if order_user_id != user_id {
return Err(AppError::Forbidden("无权操作此订单".to_string()));
}
if status != "pending" {
return Err(AppError::BadRequest(format!("订单状态为 {},无法取消", status)));
}
sqlx::query("UPDATE payment_orders SET status = 'cancelled' WHERE order_no = $1")
.bind(order_no)
.execute(pool)
.await
.map_err(|e| AppError::Database(format!("取消订单失败: {}", e)))?;
let _ = insert_payment_audit_log(pool, order_no, user_id, "cancelled", Some(user_id),
Some("用户主动取消待支付订单")).await;
Ok(())
}
/// 管理员手动退款(标记订单为 refunded + 重新计算会员)
pub async fn admin_refund_order(
pool: &PgPool,
order_no: &str,
admin_user_id: i32,
) -> Result<(), AppError> {
// 查出订单信息
let order = sqlx::query_as::<_, (i32, String)>(
r#"SELECT user_id, status FROM payment_orders WHERE order_no = $1"#,
)
.bind(order_no)
.fetch_optional(pool)
.await
.map_err(|e| AppError::Database(format!("查询订单失败: {}", e)))?;
let (user_id, status) = match order {
Some(o) => o,
None => return Err(AppError::NotFound("订单不存在".to_string())),
};
if status != "paid" && status != "pending" {
return Err(AppError::BadRequest(format!("订单状态为 {},无法退款", status)));
}
// 标记为 refunded
sqlx::query("UPDATE payment_orders SET status = 'refunded' WHERE order_no = $1")
.bind(order_no)
.execute(pool)
.await
.map_err(|e| AppError::Database(format!("退款标记失败: {}", e)))?;
// 如果订单是已支付状态,重新计算会员
if status == "paid" {
// 检查该用户是否有其他有效的已支付订单
let other_active: (i64,) = sqlx::query_as(
r#"
SELECT COUNT(*) FROM payment_orders
WHERE user_id = $1
AND status = 'paid'
AND order_no != $2
AND (expires_at IS NULL OR expires_at > NOW())
"#,
)
.bind(user_id)
.bind(order_no)
.fetch_one(pool)
.await
.map_err(|e| AppError::Database(format!("查询其他有效订单失败: {}", e)))?;
if other_active.0 == 0 {
sqlx::query(
"UPDATE users SET is_paid = false, paid_expires_at = NULL WHERE id = $1",
)
.bind(user_id)
.execute(pool)
.await
.map_err(|e| AppError::Database(format!("撤销会员失败: {}", e)))?;
tracing::info!("管理员退款: 用户 {} 的会员因订单 {} 退款已被撤销", user_id, order_no);
} else {
tracing::info!(
"管理员退款: 用户 {} 有其他有效订单({}笔),保留会员",
user_id,
other_active.0
);
}
}
let detail = if status == "paid" { "管理员手动退款(已支付订单)" } else { "管理员取消订单(待支付订单)" };
let _ = insert_payment_audit_log(pool, order_no, user_id, "refunded",
Some(admin_user_id), Some(detail)).await;
Ok(())
}