订单数据统计

This commit is contained in:
马梓彭 2026-05-15 14:03:05 +08:00
parent 8c92e13e48
commit 5bb4bd2d00
3 changed files with 156 additions and 0 deletions

View File

@ -397,3 +397,29 @@ public class RefundOrderInput
/// </summary>
public List<long>? PersonIds { get; set; }
}
/// <summary>
/// 订单统计输出
/// </summary>
public class OrderStatsOutput
{
/// <summary>
/// 原金额:所有支付订单(排除报名失败)的原始报名费用总和
/// </summary>
public decimal TotalOriginalAmount { get; set; }
/// <summary>
/// 优惠金额:所有支付订单(排除报名失败)的折扣金额总和
/// </summary>
public decimal TotalDiscountAmount { get; set; }
/// <summary>
/// 实付金额:所有实际收款的金额总和,排除报名失败状态的订单记录
/// </summary>
public decimal TotalActualAmount { get; set; }
/// <summary>
/// 退款金额:所有退款数据中的金额总和,排除报名失败状态的退款记录
/// </summary>
public decimal TotalRefundAmount { get; set; }
}

View File

@ -824,4 +824,104 @@ public class OrderService : BaseService<YD_Event.Core.Entities.Order>, ITransien
style.VerticalAlignment = ExcelVerticalAlignment.Center;
SetCellBorders(range, ExcelBorderStyle.Thin);
}
/// <summary>
/// 获取订单统计数据
/// </summary>
[DisplayName("获取订单统计数据")]
[HttpGet("stats")]
public async Task<OrderStatsOutput> GetStats([FromQuery] OrderQueryInput input)
{
var userId = _authManager.UserId;
// 判断是否是单位认证账号
var certification = await _db.Queryable<MerchantCertification>()
.FirstAsync(c => c.UserId == userId && c.AuditStatus == AuditStatus.Pass && !c.DeleteMark);
var query = _orderRepository.AsQueryable()
.LeftJoin<EventInfo>((o, e) => o.EventId == e.Id)
.LeftJoin<YD_Event.Core.Entities.Merchant>((o, e, m) => o.MerchantId == m.Id)
.LeftJoin<EventRegistration>((o, e, m, r) => o.RegistrationId == r.Id)
.LeftJoin<YD_Event.Core.Entities.Order>((o, e, m, r, ro) => o.RelatedOrderId == ro.Id)
// 默认只统计已完成支付流程的订单(已支付、已发货、已完成、已退款、报名失败)
.WhereIF(!input.OrderStatus.HasValue, (o, e, m, r, ro) =>
o.OrderStatus == OrderStatus.Paid ||
o.OrderStatus == OrderStatus.Shipped ||
o.OrderStatus == OrderStatus.Completed ||
o.OrderStatus == OrderStatus.Refunded ||
o.OrderStatus == OrderStatus.RegistrationFailed)
.WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), (o, e, m, r, ro) => o.OrderNo.Contains(input.OrderNo))
.WhereIF(!string.IsNullOrWhiteSpace(input.EventName), (o, e, m, r, ro) => e.EventName.Contains(input.EventName))
.WhereIF(input.OrderType.HasValue, (o, e, m, r, ro) => o.OrderType == input.OrderType)
.WhereIF(input.OrderStatus.HasValue, (o, e, m, r, ro) => o.OrderStatus == input.OrderStatus)
.WhereIF(input.PaymentMethod.HasValue, (o, e, m, r, ro) => r.PaymentMethod == input.PaymentMethod)
.WhereIF(input.RegistrationMode.HasValue, (o, e, m, r, ro) => r.RegistrationMode == input.RegistrationMode)
.WhereIF(!string.IsNullOrWhiteSpace(input.ContactPhone), (o, e, m, r, ro) => r.ContactPhone.Contains(input.ContactPhone))
.WhereIF(input.StartTime.HasValue, (o, e, m, r, ro) => o.CreatedTime >= input.StartTime)
.WhereIF(input.EndTime.HasValue, (o, e, m, r, ro) => o.CreatedTime <= input.EndTime);
// 权限判断:如果是单位认证用户,只能查看自己单位认证的订单
if (certification != null && !_authManager.IsSuperAdmin)
{
query = query.Where((o, e, m, r, ro) => o.MerchantCertificationId == certification.Id);
}
var list = await query.Select((o, e, m, r, ro) => new OrderListOutput
{
OrderNo = o.OrderNo,
UnitName = SqlFunc.IsNullOrEmpty(m.MerchantName) ? "/" : m.MerchantName,
EventName = e.EventName,
OrderType = o.OrderType == 1 ? "收入" : "退款",
RelatedOrderNo = ro.OrderNo,
PaymentMethod = r.PaymentMethod == 2 ? "线上" : "线下",
RegistrationMode = r.RegistrationMode == 1 ? "个人" : "团队",
ContactName = r.ContactName,
ContactPhone = r.ContactPhone,
OriginalAmount = o.OriginalAmount,
DiscountAmount = o.DiscountAmount,
// 收款订单:实付金额=原金额-优惠金额;退款订单:显示原始订单的实付金额
ActualAmount = o.OrderType == 1
? (o.OriginalAmount - o.DiscountAmount > 0 ? o.OriginalAmount - o.DiscountAmount : 0)
: o.ActualAmount,
OrderStatus = o.OrderStatus,
OrderStatusText =
o.OrderStatus == OrderStatus.Pending ? "待支付" :
o.OrderStatus == OrderStatus.Paid ? "已支付" :
o.OrderStatus == OrderStatus.Cancelled ? "已取消" :
o.OrderStatus == OrderStatus.Refunded ? "已退款" :
o.OrderStatus == OrderStatus.Shipped ? "已发货" :
o.OrderStatus == OrderStatus.Completed ? "已完成" :
o.OrderStatus == OrderStatus.RegistrationFailed ? "报名失败" : "",
CreatedTime = o.CreatedTime,
RefundAmount = o.OrderType == 2 ? o.ActualAmount : 0,
RelatedOrderActualAmount = o.OrderType == 2 ? (ro.OriginalAmount - ro.DiscountAmount) : null,
IsRefundOrder = o.OrderType == 2,
PayeeName = o.PayeeName,
PayeeBankName = o.PayeeBankName,
PayeeBankAccount = o.PayeeBankAccount
})
.ToListAsync();
// 计算统计数据(与导出功能保持完全一致的逻辑)
// 1. 原金额:所有支付订单(排除报名失败)的原始报名费用总和
var paymentOrders = list.Where(x => x.OrderType == "收入" && x.OrderStatus != OrderStatus.RegistrationFailed);
var totalOriginal = paymentOrders.Sum(x => x.OriginalAmount);
// 2. 优惠金额:所有支付订单(排除报名失败)的折扣金额总和
var totalDiscount = paymentOrders.Sum(x => x.DiscountAmount);
// 3. 退款金额:所有退款数据中的金额总和,排除报名失败状态的退款记录
var refundOrders = list.Where(x => x.OrderType == "退款" && x.OrderStatus != OrderStatus.RegistrationFailed);
var totalRefund = refundOrders.Sum(x => x.ActualAmount);
// 4. 实付金额:所有实际收款的金额总和,排除报名失败状态的订单记录
var totalActual = paymentOrders.Sum(x => x.ActualAmount);
return new OrderStatsOutput
{
TotalOriginalAmount = totalOriginal,
TotalDiscountAmount = totalDiscount,
TotalActualAmount = totalActual,
TotalRefundAmount = totalRefund
};
}
}

View File

@ -11299,6 +11299,31 @@
要取消的队员ID列表(部分取消时使用)
</summary>
</member>
<member name="T:YD_Event.Application.Order.Dtos.OrderStatsOutput">
<summary>
订单统计输出
</summary>
</member>
<member name="P:YD_Event.Application.Order.Dtos.OrderStatsOutput.TotalOriginalAmount">
<summary>
原金额:所有支付订单(排除报名失败)的原始报名费用总和
</summary>
</member>
<member name="P:YD_Event.Application.Order.Dtos.OrderStatsOutput.TotalDiscountAmount">
<summary>
优惠金额:所有支付订单(排除报名失败)的折扣金额总和
</summary>
</member>
<member name="P:YD_Event.Application.Order.Dtos.OrderStatsOutput.TotalActualAmount">
<summary>
实付金额:所有实际收款的金额总和,排除报名失败状态的订单记录
</summary>
</member>
<member name="P:YD_Event.Application.Order.Dtos.OrderStatsOutput.TotalRefundAmount">
<summary>
退款金额:所有退款数据中的金额总和,排除报名失败状态的退款记录
</summary>
</member>
<member name="T:YD_Event.Application.Order.Dtos.OrderQueryInput">
<summary>
订单查询输入
@ -11419,6 +11444,11 @@
设置数据行样式
</summary>
</member>
<member name="M:YD_Event.Application.Order.OrderService.GetStats(YD_Event.Application.Order.Dtos.OrderQueryInput)">
<summary>
获取订单统计数据
</summary>
</member>
<member name="T:YD_Event.Application.Organization.Dtos.AddOrgInput">
<summary>
添加机构输入