390 lines
16 KiB
C#
390 lines
16 KiB
C#
using HoneyBox.Admin.Business.Models.Statistics;
|
||
using HoneyBox.Admin.Business.Services.Interfaces;
|
||
using HoneyBox.Model.Data;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Logging;
|
||
|
||
namespace HoneyBox.Admin.Business.Services;
|
||
|
||
/// <summary>
|
||
/// 统计服务实现
|
||
/// </summary>
|
||
public class StatisticsService : IStatisticsService
|
||
{
|
||
private readonly HoneyBoxDbContext _dbContext;
|
||
private readonly ILogger<StatisticsService> _logger;
|
||
|
||
public StatisticsService(HoneyBoxDbContext dbContext, ILogger<StatisticsService> logger)
|
||
{
|
||
_dbContext = dbContext;
|
||
_logger = logger;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取今日订单统计数据
|
||
/// </summary>
|
||
public async Task<TodayOrderStatsResponse> GetTodayOrderStatsAsync()
|
||
{
|
||
var today = DateTime.Today;
|
||
var tomorrow = today.AddDays(1);
|
||
|
||
// 排除测试用户的订单
|
||
var todayOrdersQuery = _dbContext.Orders
|
||
.Where(o => o.CreatedAt >= today && o.CreatedAt < tomorrow)
|
||
.Join(_dbContext.Users.Where(u => u.IsTest == 0),
|
||
o => o.UserId,
|
||
u => u.Id,
|
||
(o, u) => o);
|
||
|
||
// 今日已支付订单查询
|
||
var todayPaidOrdersQuery = todayOrdersQuery.Where(o => o.Status == 1);
|
||
|
||
// 发起订单数(今日创建的订单总数)
|
||
var initiateOrderCount = await todayOrdersQuery.CountAsync();
|
||
|
||
// 支付订单数(今日支付成功的订单数)
|
||
var paidOrderCount = await todayPaidOrdersQuery.CountAsync();
|
||
|
||
// 消费人数(今日有消费的用户数,去重)
|
||
var userCount = await todayPaidOrdersQuery
|
||
.Select(o => o.UserId)
|
||
.Distinct()
|
||
.CountAsync();
|
||
|
||
// 订单总金额(今日订单折后总金额)
|
||
var orderZheTotal = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.OrderZheTotal) ?? 0;
|
||
|
||
// 出货总金额(今日出货奖品总价值)- 从订单详情表获取
|
||
var goodsTotalAmount = await _dbContext.OrderItems
|
||
.Where(oi => oi.CreatedAt >= today && oi.CreatedAt < tomorrow)
|
||
.Join(_dbContext.Users.Where(u => u.IsTest == 0),
|
||
oi => oi.UserId,
|
||
u => u.Id,
|
||
(oi, u) => oi)
|
||
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
|
||
|
||
// 优惠券抵扣(今日优惠券抵扣总额)
|
||
var useCoupon = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.UseCoupon) ?? 0;
|
||
|
||
// RMB支付(今日微信支付总额)
|
||
var price = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.Price) ?? 0;
|
||
|
||
// 钻石支付(今日钻石支付总额)
|
||
var useMoney = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.UseMoney) ?? 0;
|
||
|
||
// UU币支付(今日UU币支付总额)
|
||
var useIntegral = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.UseIntegral) ?? 0;
|
||
|
||
// 达达券支付(今日达达券支付总额)
|
||
var useMoney2 = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.UseMoney2) ?? 0;
|
||
|
||
return new TodayOrderStatsResponse
|
||
{
|
||
InitiateOrderCount = initiateOrderCount,
|
||
PaidOrderCount = paidOrderCount,
|
||
UserCount = userCount,
|
||
OrderZheTotal = orderZheTotal,
|
||
GoodsTotalAmount = goodsTotalAmount,
|
||
UseCoupon = useCoupon,
|
||
Price = price,
|
||
UseMoney = useMoney,
|
||
UseIntegral = useIntegral,
|
||
UseMoney2 = useMoney2
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取货币信息统计数据
|
||
/// </summary>
|
||
public async Task<CurrencyInfoStatsResponse> GetCurrencyInfoStatsAsync()
|
||
{
|
||
var today = DateTime.Today;
|
||
var tomorrow = today.AddDays(1);
|
||
var yesterday = today.AddDays(-1);
|
||
|
||
// 排除测试用户
|
||
var nonTestUserIds = _dbContext.Users
|
||
.Where(u => u.IsTest == 0)
|
||
.Select(u => u.Id);
|
||
|
||
// 钻石流水查询(ProfitMoney表)
|
||
var todayMoneyQuery = _dbContext.ProfitMoneys
|
||
.Where(p => p.CreatedAt >= today && p.CreatedAt < tomorrow)
|
||
.Where(p => nonTestUserIds.Contains(p.UserId));
|
||
|
||
var yesterdayMoneyQuery = _dbContext.ProfitMoneys
|
||
.Where(p => p.CreatedAt >= yesterday && p.CreatedAt < today)
|
||
.Where(p => nonTestUserIds.Contains(p.UserId));
|
||
|
||
// 今日发放钻石(ChangeMoney > 0)
|
||
var todayAddMoney = await todayMoneyQuery
|
||
.Where(p => p.ChangeMoney > 0)
|
||
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
|
||
|
||
// 今日消费钻石(ChangeMoney < 0,取绝对值)
|
||
var todayUseMoney = await todayMoneyQuery
|
||
.Where(p => p.ChangeMoney < 0)
|
||
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
|
||
|
||
// 昨日发放钻石
|
||
var yesterdayAddMoney = await yesterdayMoneyQuery
|
||
.Where(p => p.ChangeMoney > 0)
|
||
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
|
||
|
||
// 昨日消费钻石
|
||
var yesterdayUseMoney = await yesterdayMoneyQuery
|
||
.Where(p => p.ChangeMoney < 0)
|
||
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
|
||
|
||
// UU币流水查询(ProfitIntegral表)
|
||
var todayIntegralQuery = _dbContext.ProfitIntegrals
|
||
.Where(p => p.CreatedAt >= today && p.CreatedAt < tomorrow)
|
||
.Where(p => nonTestUserIds.Contains(p.UserId));
|
||
|
||
var yesterdayIntegralQuery = _dbContext.ProfitIntegrals
|
||
.Where(p => p.CreatedAt >= yesterday && p.CreatedAt < today)
|
||
.Where(p => nonTestUserIds.Contains(p.UserId));
|
||
|
||
// 今日发放UU币
|
||
var todayAddIntegral = await todayIntegralQuery
|
||
.Where(p => p.ChangeMoney > 0)
|
||
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
|
||
|
||
// 今日消费UU币
|
||
var todayUseIntegral = await todayIntegralQuery
|
||
.Where(p => p.ChangeMoney < 0)
|
||
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
|
||
|
||
// 昨日发放UU币
|
||
var yesterdayAddIntegral = await yesterdayIntegralQuery
|
||
.Where(p => p.ChangeMoney > 0)
|
||
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
|
||
|
||
// 昨日消费UU币
|
||
var yesterdayUseIntegral = await yesterdayIntegralQuery
|
||
.Where(p => p.ChangeMoney < 0)
|
||
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
|
||
|
||
// 达达券流水查询(ProfitMoney2表)
|
||
var todayMoney2Query = _dbContext.ProfitMoney2s
|
||
.Where(p => p.CreatedAt >= today && p.CreatedAt < tomorrow)
|
||
.Where(p => nonTestUserIds.Contains(p.UserId));
|
||
|
||
var yesterdayMoney2Query = _dbContext.ProfitMoney2s
|
||
.Where(p => p.CreatedAt >= yesterday && p.CreatedAt < today)
|
||
.Where(p => nonTestUserIds.Contains(p.UserId));
|
||
|
||
// 今日发放达达券
|
||
var todayAddMoney2 = await todayMoney2Query
|
||
.Where(p => p.ChangeMoney > 0)
|
||
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
|
||
|
||
// 今日消费达达券
|
||
var todayUseMoney2 = await todayMoney2Query
|
||
.Where(p => p.ChangeMoney < 0)
|
||
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
|
||
|
||
// 昨日发放达达券
|
||
var yesterdayAddMoney2 = await yesterdayMoney2Query
|
||
.Where(p => p.ChangeMoney > 0)
|
||
.SumAsync(p => (decimal?)p.ChangeMoney) ?? 0;
|
||
|
||
// 昨日消费达达券
|
||
var yesterdayUseMoney2 = await yesterdayMoney2Query
|
||
.Where(p => p.ChangeMoney < 0)
|
||
.SumAsync(p => (decimal?)(-p.ChangeMoney)) ?? 0;
|
||
|
||
return new CurrencyInfoStatsResponse
|
||
{
|
||
TodayAddMoney = todayAddMoney,
|
||
TodayUseMoney = todayUseMoney,
|
||
YesterdayAddMoney = yesterdayAddMoney,
|
||
YesterdayUseMoney = yesterdayUseMoney,
|
||
TodayAddIntegral = todayAddIntegral,
|
||
TodayUseIntegral = todayUseIntegral,
|
||
YesterdayAddIntegral = yesterdayAddIntegral,
|
||
YesterdayUseIntegral = yesterdayUseIntegral,
|
||
TodayAddMoney2 = todayAddMoney2,
|
||
TodayUseMoney2 = todayUseMoney2,
|
||
YesterdayAddMoney2 = yesterdayAddMoney2,
|
||
YesterdayUseMoney2 = yesterdayUseMoney2
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取收入汇总统计数据
|
||
/// </summary>
|
||
public async Task<IncomeSummaryStatsResponse> GetIncomeSummaryStatsAsync()
|
||
{
|
||
var today = DateTime.Today;
|
||
var tomorrow = today.AddDays(1);
|
||
|
||
// 排除测试用户
|
||
var nonTestUserIds = _dbContext.Users
|
||
.Where(u => u.IsTest == 0)
|
||
.Select(u => u.Id);
|
||
|
||
// 今日已支付订单查询(排除测试用户)
|
||
var todayPaidOrdersQuery = _dbContext.Orders
|
||
.Where(o => o.CreatedAt >= today && o.CreatedAt < tomorrow && o.Status == 1)
|
||
.Where(o => nonTestUserIds.Contains(o.UserId));
|
||
|
||
// RMB收入(今日微信支付总额)
|
||
var rmbIncome = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.Price) ?? 0;
|
||
|
||
// 钻石支付收入
|
||
var diamondPayment = await todayPaidOrdersQuery
|
||
.SumAsync(o => (decimal?)o.UseMoney) ?? 0;
|
||
|
||
// 订单收入(RMB + 钻石)
|
||
var todayIncome = rmbIncome + diamondPayment;
|
||
|
||
// 钻石商城收入(今日钻石商城已支付订单)
|
||
var diamondIncome = await _dbContext.DiamondOrders
|
||
.Where(d => d.CreatedAt >= today && d.CreatedAt < tomorrow && d.Status == "paid")
|
||
.Where(d => nonTestUserIds.Contains((int)d.UserId))
|
||
.SumAsync(d => (decimal?)d.AmountPaid) ?? 0;
|
||
|
||
// 其他收入(暂时设为0,可根据实际业务扩展)
|
||
var otherIncome = 0m;
|
||
|
||
// 订单出货(今日出货奖品总价值)- 从订单详情表获取
|
||
var shippedToday = await _dbContext.OrderItems
|
||
.Where(oi => oi.CreatedAt >= today && oi.CreatedAt < tomorrow)
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
|
||
|
||
// 支出(暂时设为0,可根据实际业务扩展)
|
||
var expenses = 0m;
|
||
|
||
// 当天发货金额(今日申请发货的奖品总价值,status=2表示已发货)
|
||
var todayShippedAmount = await _dbContext.OrderItems
|
||
.Where(oi => oi.CreatedAt >= today && oi.CreatedAt < tomorrow && oi.Status == 2)
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
|
||
|
||
// 当天用户剩余达达券(所有非测试用户的达达券余额总和)
|
||
var remainingCoupon = await _dbContext.Users
|
||
.Where(u => u.IsTest == 0)
|
||
.SumAsync(u => (decimal?)u.Money2) ?? 0;
|
||
|
||
// 盒柜剩余价值(今日用户盒柜中奖品总价值,status=0表示待处理)
|
||
var boxRemaining = await _dbContext.OrderItems
|
||
.Where(oi => oi.Status == 0)
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
|
||
|
||
// 利润计算:收入 - 发货金额 - 用户剩余达达券 - 盒柜剩余
|
||
var profit = todayIncome - todayShippedAmount - remainingCoupon - boxRemaining;
|
||
|
||
// 利润计算公式
|
||
var formula = $"利润 = 订单收入({todayIncome:F2}) - 发货金额({todayShippedAmount:F2}) - 用户剩余达达券({remainingCoupon:F2}) - 盒柜剩余({boxRemaining:F2})";
|
||
|
||
return new IncomeSummaryStatsResponse
|
||
{
|
||
TodayIncome = todayIncome,
|
||
RmbIncome = rmbIncome,
|
||
DiamondIncome = diamondIncome,
|
||
OtherIncome = otherIncome,
|
||
ShippedToday = shippedToday,
|
||
Expenses = expenses,
|
||
TodayShipped = todayShippedAmount,
|
||
RemainingCoupon = remainingCoupon,
|
||
BoxRemaining = boxRemaining,
|
||
Profit = profit,
|
||
Formula = formula
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取用户统计数据
|
||
/// </summary>
|
||
public async Task<UserStatsResponse> GetUserStatsAsync()
|
||
{
|
||
// 排除测试用户
|
||
var nonTestUsersQuery = _dbContext.Users.Where(u => u.IsTest == 0);
|
||
var nonTestUserIds = nonTestUsersQuery.Select(u => u.Id);
|
||
|
||
// 绑定手机号人数(手机号不为空且不为空字符串的用户数)
|
||
var userRegisterCount = await nonTestUsersQuery
|
||
.Where(u => u.Mobile != null && u.Mobile != "")
|
||
.CountAsync();
|
||
|
||
// 抽奖人数(有抽奖记录的用户总数,去重)
|
||
var consumingUserCount = await _dbContext.OrderItems
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.Select(oi => oi.UserId)
|
||
.Distinct()
|
||
.CountAsync();
|
||
|
||
// 用户剩余钻石(所有非测试用户的钻石余额总和)
|
||
var userMoney = await nonTestUsersQuery
|
||
.SumAsync(u => (decimal?)u.Money) ?? 0;
|
||
|
||
// 用户剩余UU币(所有非测试用户的UU币余额总和)
|
||
var userIntegral = await nonTestUsersQuery
|
||
.SumAsync(u => (decimal?)u.Integral) ?? 0;
|
||
|
||
// 用户剩余达达券(所有非测试用户的达达券余额总和)
|
||
var userMoney2 = await nonTestUsersQuery
|
||
.SumAsync(u => (decimal?)u.Money2) ?? 0;
|
||
|
||
// 微信支付金额(历史微信支付总额,排除测试用户)
|
||
var orderPriceTotal = await _dbContext.Orders
|
||
.Where(o => o.Status == 1)
|
||
.Where(o => nonTestUserIds.Contains(o.UserId))
|
||
.SumAsync(o => (decimal?)o.Price) ?? 0;
|
||
|
||
// 订单支付数量(历史支付成功订单总数,排除测试用户)
|
||
var orderTotalCount = await _dbContext.Orders
|
||
.Where(o => o.Status == 1)
|
||
.Where(o => nonTestUserIds.Contains(o.UserId))
|
||
.CountAsync();
|
||
|
||
// 用户出货总金额(所有中奖记录的奖品总价值,排除测试用户)
|
||
var totalGoodsAmount = await _dbContext.OrderItems
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
|
||
|
||
// 用户盒柜剩余价值(status=0表示待处理的奖品,排除测试用户)
|
||
var boxRemainingValue = await _dbContext.OrderItems
|
||
.Where(oi => oi.Status == 0)
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
|
||
|
||
// 用户已兑换的达达券(status=1表示已回收的奖品回收金额总和,排除测试用户)
|
||
var exchangedCoupon = await _dbContext.OrderItems
|
||
.Where(oi => oi.Status == 1)
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.SumAsync(oi => (decimal?)oi.GoodslistMoney) ?? 0;
|
||
|
||
// 用户已发货金额(status=2表示已发货的奖品价值总和,排除测试用户)
|
||
var shippedAmount = await _dbContext.OrderItems
|
||
.Where(oi => oi.Status == 2)
|
||
.Where(oi => nonTestUserIds.Contains(oi.UserId))
|
||
.SumAsync(oi => (decimal?)oi.GoodslistPrice) ?? 0;
|
||
|
||
return new UserStatsResponse
|
||
{
|
||
UserRegisterCount = userRegisterCount,
|
||
ConsumingUserCount = consumingUserCount,
|
||
UserMoney = userMoney,
|
||
UserIntegral = userIntegral,
|
||
UserMoney2 = userMoney2,
|
||
OrderPriceTotal = orderPriceTotal,
|
||
OrderTotalCount = orderTotalCount,
|
||
TotalGoodsAmount = totalGoodsAmount,
|
||
BoxRemainingValue = boxRemainingValue,
|
||
ExchangedCoupon = exchangedCoupon,
|
||
ShippedAmount = shippedAmount
|
||
};
|
||
}
|
||
}
|