HaniBlindBox/server/HoneyBox/src/HoneyBox.Admin.Business/Services/StatisticsService.cs
2026-01-19 00:09:38 +08:00

390 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
};
}
}