zhengyuxuan
2025-04-07 6b9333d8ba03965a221cec5ba8249900d0c3683c
LifePayment/LifePayment.Application/LifePay/StatisticsService.cs
@@ -16,6 +16,11 @@
using Volo.Abp.EventBus.Distributed;
using static Nest.FileSystemStats;
using Microsoft.EntityFrameworkCore;
using System.Threading.Channels;
using ZeroD.Util;
using NPOI.SS.Formula.Functions;
using System.Security.Principal;
using StackExchange.Redis;
namespace LifePayment.Application.LifePay
{
@@ -24,75 +29,331 @@
        private readonly IRepository<LifePayOrder, Guid> _lifePayOrderRepository;
        private readonly IRepository<LifePayUser, Guid> _lifePayUserRepository;
        private readonly IRepository<DallyStatistics, Guid> _dallyStatisticsRepository;
        private readonly IRepository<LifePayChannlesRake, Guid> _lifePayChannlesRakeRepository;
        private readonly IRepository<LifePayRechargeReceipts, Guid> _lifePayRechargeReceiptsRepository;
        private readonly IRepository<LifePayChannles, Guid> _lifePayChannlesRep;
        public StatisticsService(
                              IRepository<LifePayOrder, Guid> lifePayOrderRepository,
                              IRepository<LifePayUser, Guid> lifePayUserRepository,
                            IRepository<DallyStatistics, Guid> dallyStatisticsRepository)
                                IRepository<DallyStatistics, Guid> dallyStatisticsRepository,
                                IRepository<LifePayChannlesRake, Guid> lifePayChannlesRakeRepository,
                                IRepository<LifePayRechargeReceipts, Guid> lifePayRechargeReceiptsRepository,
                                IRepository<LifePayChannles, Guid> lifePayChannlesRep)
        {
            _lifePayOrderRepository = lifePayOrderRepository;
            _lifePayUserRepository = lifePayUserRepository;
            _dallyStatisticsRepository = dallyStatisticsRepository;
            _lifePayChannlesRakeRepository = lifePayChannlesRakeRepository;
            _lifePayRechargeReceiptsRepository = lifePayRechargeReceiptsRepository;
            _lifePayChannlesRep = lifePayChannlesRep;
        }
        public async Task<TopStatisticsOutput> GetTopStatistics()
        /// <summary>
        /// 顶部统计
        /// </summary>
        /// <param name="channleId"></param>
        /// <returns></returns>
        public async Task<TopStatisticsOutput> GetTopStatistics(List<string> channleList)
        {
            var today = DateTime.Now.Date;
            var statistics = await _dallyStatisticsRepository.Where(x => x.CreationTime.Date == today).FirstOrDefaultAsync();
            if (statistics == null)
            var statistics = await _dallyStatisticsRepository.Where(x => x.CreationTime.Date == today)
                .WhereIf(channleList.Count() > 0, x => channleList.Contains(x.ChannelId))
                .ToListAsync();
            var totalRechargeReceipts = await _lifePayRechargeReceiptsRepository.Where(x => x.CreationTime < today).SumAsync(x => x.RechargeAmount);
            if (statistics == null || statistics.Count() == 0)
            {
                var accumulatedReceipts = await _lifePayOrderRepository.Where(x => x.CreationTime < today).SumAsync(x => x.PayAmount);
                var receiptsYesterday = await _lifePayOrderRepository.Where(x => x.CreationTime >= today.AddDays(-1) && x.CreationTime < today).SumAsync(x => x.PayAmount);
                var accumulatedOrders = await _lifePayOrderRepository.Where(x => x.CreationTime < today).CountAsync();
                var accumulatedIncome = await _lifePayOrderRepository.Where(x => x.CreationTime < today).SumAsync(x => x.ActualRechargeAmount);
                var ordersNumYesterday = await _lifePayOrderRepository.Where(x => x.CreationTime >= today.AddDays(-1) && x.CreationTime < today).CountAsync();
                var yesterdaySuccess = await _lifePayOrderRepository.Where(x => x.CreationTime >= today.AddDays(-1) && x.CreationTime < today && x.LifePayOrderStatus == LifePayOrderStatusEnum.已完成).CountAsync();
                var yesterdayFail = await _lifePayOrderRepository.Where(x => x.CreationTime >= today.AddDays(-1) && x.CreationTime < today && x.LifePayOrderStatus == LifePayOrderStatusEnum.退款失败).CountAsync();
                var accumulatedUsers = await _lifePayUserRepository.CountAsync();
                var entity = new DallyStatistics()
                TopStatisticsOutput topStatisticsOutput = new TopStatisticsOutput() { };
                var allChannle = await _lifePayChannlesRep.ToListAsync();
                foreach (var item in allChannle)
                {
                    Id = GuidGenerator.Create(),
                    CreationTime = DateTime.Now,
                    Amount = 0,
                    AccumulatedReceipts = accumulatedReceipts,
                    ReceiptsYesterday = receiptsYesterday,
                    AccumulatedOrders = accumulatedOrders,
                    OrdersNumYesterday = ordersNumYesterday,
                    YesterdaySuccess = yesterdaySuccess,
                    YesterdayFail = yesterdayFail,
                    AccumulatedUsers = accumulatedUsers,
                };
                await _dallyStatisticsRepository.InsertAsync(entity);
                    var entity = await TopStatistics(item.ChannlesNum, today);
                    if (channleList.Count() == 0 || channleList.Contains(item.ChannlesNum))
                    {
                        topStatisticsOutput.AccumulatedReceipts += entity.AccumulatedReceipts;
                        topStatisticsOutput.AccumulatedIncome += entity.AccumulatedIncome;
                        topStatisticsOutput.ReceiptsYesterday += entity.ReceiptsYesterday;
                        topStatisticsOutput.AccumulatedOrders += entity.AccumulatedOrders;
                        topStatisticsOutput.OrdersNumYesterday += entity.OrdersNumYesterday;
                        topStatisticsOutput.YesterdaySuccess += entity.YesterdaySuccess;
                        topStatisticsOutput.YesterdayFail += entity.YesterdayFail;
                        topStatisticsOutput.AccumulatedUsers += entity.AccumulatedUsers;
                        topStatisticsOutput.YesterdayActiveUsers += entity.YesterdayActiveUsers;
                        topStatisticsOutput.AccumulatedChannlesRakePrice += entity.AccumulatedChannlesRakePrice;
                    }
                }
                TopStatisticsOutput topStatisticsOutput = new TopStatisticsOutput()
                if (channleList.Count() == 0)
                {
                    Amount = entity.Amount,
                    AccumulatedReceipts = entity.AccumulatedReceipts,
                    ReceiptsYesterday = entity.ReceiptsYesterday,
                    AccumulatedOrders = entity.AccumulatedOrders,
                    OrdersNumYesterday = entity.OrdersNumYesterday,
                    YesterdaySuccess = entity.YesterdaySuccess,
                    YesterdayFail = entity.YesterdayFail,
                    AccumulatedUsers = entity.AccumulatedUsers,
                };
                    /// 账户余额
                    topStatisticsOutput.Amount = totalRechargeReceipts - await _lifePayOrderRepository.Where(x => x.ACOOLYStatus == ACOOLYStatusEnum.充值成功 || x.ACOOLYStatus == ACOOLYStatusEnum.已完成 || x.ACOOLYStatus == ACOOLYStatusEnum.部分充值成功)
                      .SumAsync(x => x.PlatformDeductionAmount) ?? 0;
                }
                return topStatisticsOutput;
            }
            else
            {
                TopStatisticsOutput topStatisticsOutput = new TopStatisticsOutput()
                {
                    Amount = statistics.Amount,
                    AccumulatedReceipts = statistics.AccumulatedReceipts,
                    ReceiptsYesterday = statistics.ReceiptsYesterday,
                    AccumulatedOrders = statistics.AccumulatedOrders,
                    OrdersNumYesterday = statistics.OrdersNumYesterday,
                    YesterdaySuccess = statistics.YesterdaySuccess,
                    YesterdayFail = statistics.YesterdayFail,
                    AccumulatedUsers = statistics.AccumulatedUsers,
                    AccumulatedReceipts = statistics.Sum(s => s.AccumulatedReceipts),
                    AccumulatedIncome = statistics.Sum(s => s.AccumulatedIncome),
                    ReceiptsYesterday = statistics.Sum(s => s.ReceiptsYesterday),
                    AccumulatedOrders = statistics.Sum(s => s.AccumulatedOrders),
                    OrdersNumYesterday = statistics.Sum(s => s.OrdersNumYesterday),
                    YesterdaySuccess = statistics.Sum(s => s.YesterdaySuccess),
                    YesterdayFail = statistics.Sum(s => s.YesterdayFail),
                    AccumulatedUsers = statistics.Sum(s => s.AccumulatedUsers),
                    YesterdayActiveUsers = statistics.Sum(s => s.YesterdayActiveUsers),
                    AccumulatedChannlesRakePrice = statistics.Sum(s => s.AccumulatedChannlesRakePrice)
                };
                if (channleList.Count() == 0)
                {
                    /// 账户余额
                    topStatisticsOutput.Amount = totalRechargeReceipts - await _lifePayOrderRepository.Where(x => x.ACOOLYStatus == ACOOLYStatusEnum.充值成功 || x.ACOOLYStatus == ACOOLYStatusEnum.已完成 || x.ACOOLYStatus == ACOOLYStatusEnum.部分充值成功)
                      .SumAsync(x => x.PlatformDeductionAmount) ?? 0;
                }
                return topStatisticsOutput;
            }
        }
        /// <summary>
        /// 近30日收款数据
        /// </summary>
        /// <param name="channleList"></param>
        /// <returns></returns>
        public async Task<ReceiptsListOutPut> GetReceiptsList(List<string> channleList)
        {
            var today = DateTime.Now.Date;
            var statistics = await _dallyStatisticsRepository.Where(x => x.CreationTime.Date <= today && x.CreationTime.Date >= today.AddDays(-30))
                .WhereIf(channleList.Count() > 0, x => channleList.Contains(x.ChannelId))
                .OrderBy(o => o.CreationTime)
                .ToListAsync();
            CheckExtensions.IfTrueThrowUserFriendlyException(statistics == null, "收款统计失败");
            var groupedStatistics = statistics
                .GroupBy(x => x.CreationTime)
                .Select(g => new
                {
                    CreationTime = g.Key,
                    TotalReceiptsYesterday = g.Sum(x => x.ReceiptsYesterday),
                    TotalIncomeYesterday = g.Sum(x => x.IncomeYesterday)
                })
                .ToList();
            ReceiptsListOutPut receiptsListOutPut = new ReceiptsListOutPut();
            foreach (var item in groupedStatistics)
            {
                /// 实际收款日期
                var creationTime = item.CreationTime.AddDays(-1).ToString("yyyy-MM-dd");
                ReceiptsDetail receive = new ReceiptsDetail()
                {
                    CreationTime = creationTime,
                    Amount = item.TotalReceiptsYesterday
                };
                ReceiptsDetail income = new ReceiptsDetail()
                {
                    CreationTime = creationTime,
                    Amount = item.TotalIncomeYesterday
                };
                receiptsListOutPut.ReceiveList.Add(receive);
                receiptsListOutPut.IncomeList.Add(income);
            }
            return receiptsListOutPut;
        }
        /// <summary>
        /// 获取30天佣金
        /// </summary>
        /// <param name="channleList"></param>
        /// <returns></returns>
        public async Task<ChannlesRakeListOutPut> GetChannlesRakeList(List<string> channleList)
        {
            var today = DateTime.Now.Date;
            var statistics = await _lifePayChannlesRakeRepository.Where(x => x.FinishTime.Date <= today && x.FinishTime.Date >= today.AddDays(-30))
                            .WhereIf(channleList.Count() > 0, x => channleList.Contains(x.ChannelId))
                            .ToListAsync();
            CheckExtensions.IfTrueThrowUserFriendlyException(statistics == null, "佣金统计失败");
            var groupedStatistics = statistics
               .GroupBy(x => x.FinishTime.ToString("yyyy-MM-dd"))
               .Select(g => new
               {
                   FinishTime = g.Key,
                   ChannlesRakePrice = g.Sum(x => x.ChannlesRakePrice),
               })
               .ToList();
            ChannlesRakeListOutPut channlesRakeListOutPut = new ChannlesRakeListOutPut();
            var dateList = Enumerable.Range(1, 31)
                        .Select(i => today.AddDays(-i))
                        .ToList();
            foreach (var date in dateList)
            {
                var stat = groupedStatistics.FirstOrDefault(g => g.FinishTime == date.ToString("yyyy-MM-dd"));
                ReceiptsDetail receive = new ReceiptsDetail()
                {
                    CreationTime = date.ToString("yyyy-MM-dd"),
                    Amount = stat?.ChannlesRakePrice ?? 0
                };
                channlesRakeListOutPut.ChannlesRakeList.Add(receive);
            }
            return channlesRakeListOutPut;
        }
        public async Task<ChannelDataListOutPut> GetChannelDataList(List<string> channleList)
        {
            int maxStatisticsNumber = 5;
            /// 这里不加入.Where()会报错
            var statistics = await _lifePayChannlesRakeRepository.Where(x => x.IsDeleted == false)
                            .WhereIf(channleList.Count() > 0, x => channleList.Contains(x.ChannelId))
            .ToListAsync();
            CheckExtensions.IfTrueThrowUserFriendlyException(statistics == null, "渠道收款统计失败");
            var groupedStatistics = statistics
               .GroupBy(x => x.ChannelId)
               .Select(g => new
               {
                   ChannelId = g.Key,
                   ReceivePrice = g.Sum(x => x.PayAmount),
                   ChannlesRakePrice = g.Sum(x => x.ChannlesRakePrice),
               })
               .OrderByDescending(o => o.ReceivePrice)
               .ToList();
            ChannelDataListOutPut channelDataList = new ChannelDataListOutPut();
            foreach (var item in groupedStatistics)
            {
                ChannelDataReceive receive = new ChannelDataReceive()
                {
                    ChannelName = _lifePayChannlesRep.Where(x => x.ChannlesNum == item.ChannelId).FirstOrDefault()?.ChannlesName,
                    ReceivePrice = item.ReceivePrice,
                    ChannlesRakePrice = item.ChannlesRakePrice,
                };
                if (channelDataList.ReceiveList.Count() < maxStatisticsNumber)
                {
                    channelDataList.ReceiveList.Add(receive);
                }
            }
            /// 累计用户
            var users = await _lifePayUserRepository.Where(x => x.IsDeleted == false).WhereIf(channleList.Count() > 0, x => channleList.Contains(x.CreationChannleNum))
                .ToListAsync();
            CheckExtensions.IfTrueThrowUserFriendlyException(statistics == null, "累计用户统计失败");
            var groupedUsers = users
              .GroupBy(x => x.CreationChannleNum)
              .Select(g => new
              {
                  ChannelId = g.Key,
                  Number = g.Count(),
              })
              .OrderByDescending(o => o.Number)
              .ToList();
            foreach (var item in groupedUsers)
            {
                ChannelDataUserNumber usernumber = new ChannelDataUserNumber()
                {
                    ChannelName = _lifePayChannlesRep.Where(x => x.ChannlesNum == item.ChannelId).FirstOrDefault()?.ChannlesName,
                    Number = item.Number,
                };
                if (channelDataList.UserNumberList.Count() < maxStatisticsNumber)
                {
                    channelDataList.UserNumberList.Add(usernumber);
                }
            }
            return channelDataList;
        }
        public async Task StatisticsByDate(int days)
        {
            var today = DateTime.Now.Date;
            for (var i = 0; i < days; i++)
            {
                var statistics = await _dallyStatisticsRepository.Where(x => x.CreationTime.Date == today)
                .ToListAsync();
                if (statistics == null || statistics.Count() == 0)
                {
                    TopStatisticsOutput topStatisticsOutput = new TopStatisticsOutput() { };
                    var allChannle = await _lifePayChannlesRep.ToListAsync();
                    foreach (var item in allChannle)
                    {
                        var entity = await TopStatistics(item.ChannlesNum, today);
                    }
                }
                today = today.AddDays(-1);
            }
        }
        private async Task<DallyStatistics> TopStatistics(string channleId, DateTime today)
        {
            var lifepayOrderBaseList = await _lifePayOrderRepository.Where(x => x.CreationTime < today)
                .WhereIf(!string.IsNullOrWhiteSpace(channleId), x => x.ChannelId == channleId).ToListAsync();
            /// 累计收款:统计平台账户下订单创建时间在昨天及之前收到的【用户支付成功的金额-退款给用户的金额】;
            var accumulatedReceipts = lifepayOrderBaseList.Where(x => x.PayStatus != LifePayStatusEnum.未支付).Sum(x => x.PayAmount)
               - lifepayOrderBaseList.Where(x => x.LifePayRefundStatus == LifePayRefundStatusEnum.已退款).Sum(x => (x.RefundPrice ?? 0));
            /// 昨日收款:统计平台账户下订单创建时间在昨天收到的【用户支付成功的金额-退款给用户的金额】;
            var receiptsYesterday = lifepayOrderBaseList.Where(x => x.CreationTime >= today.AddDays(-1) && x.PayStatus == LifePayStatusEnum.已支付)
                .Sum(x => x.PayAmount) -
                lifepayOrderBaseList.Where(x => x.CreationTime >= today.AddDays(-1) && x.LifePayRefundStatus == LifePayRefundStatusEnum.已退款)
                .Sum(x => (x.RefundPrice ?? 0));
            /// 累计收入:统计平台账户下订单状态为“已完成”且订单创建时间在昨天及之前收到的【用户实付金额-平台扣款金额-部分退款金额】;
            var accumulatedIncome = lifepayOrderBaseList.Where(x => x.LifePayOrderStatus == LifePayOrderStatusEnum.已完成)
              .Sum(x => x.PayAmount - (x.PlatformDeductionAmount ?? 0) - (x.RefundPrice ?? 0));
            /// 昨日收入:统计平台账户下订单状态为“已完成”且订单创建时间在昨天收到的【用户实付金额-平台扣款金额-部分退款金额】;
            var yesterdayIncome = lifepayOrderBaseList.Where(x => x.CreationTime >= today.AddDays(-1) && x.LifePayOrderStatus == LifePayOrderStatusEnum.已完成)
                .Sum(x => x.PayAmount - (x.PlatformDeductionAmount ?? 0) - (x.RefundPrice ?? 0));
            /// 累计下单:统计平台中订单下单时间在昨天及之前时间的订单记录;
            var accumulatedOrders = lifepayOrderBaseList.Count();
            /// 昨日下单:统计平台中订单下单时间在昨天的订单记录;
            var ordersNumYesterday = lifepayOrderBaseList.Where(x => x.CreationTime >= today.AddDays(-1)).Count();
            /// 昨日成功:统计平台中订单状态为“已完成/部分充值成功”且订单下单时间在昨天的订单记录;
            var yesterdaySuccess = lifepayOrderBaseList.Where(x => x.CreationTime >= today.AddDays(-1) && x.LifePayOrderStatus == LifePayOrderStatusEnum.已完成)
                .Count();
            /// 昨日失败:统计平台中订单状态为“充值失败/已退款”且订单下单时间在昨天的订单记录;
            var yesterdayFail = lifepayOrderBaseList.Where(x => x.CreationTime >= today.AddDays(-1) && x.LifePayOrderStatus == LifePayOrderStatusEnum.已退款)
                .Count();
            /// 累计用户
            var accumulatedUsers = await _lifePayUserRepository.Where(x => x.CreationTime < today)
                .WhereIf(!string.IsNullOrWhiteSpace(channleId), x => x.CreationChannleNum == channleId).CountAsync();
            /// 昨日活跃用户
            var yesterdayActiveUsers = await (from a in _lifePayUserRepository
                                              join b in _lifePayOrderRepository on a.Id equals b.UserId
                                              where b.CreationTime >= today.AddDays(-1) && b.CreationTime < today
                                              && (b.ACOOLYStatus == ACOOLYStatusEnum.充值中 || b.ACOOLYStatus == ACOOLYStatusEnum.充值成功 || b.ACOOLYStatus == ACOOLYStatusEnum.已完成 || b.ACOOLYStatus == ACOOLYStatusEnum.部分充值成功)
                                              select b).Distinct().CountAsync();
            /// 累计佣金
            var accumulatedChannlesRakePrice = await _lifePayChannlesRakeRepository.Where(x => x.FinishTime < today)
                .WhereIf(!string.IsNullOrWhiteSpace(channleId), x => x.ChannelId == channleId).SumAsync(x => x.ChannlesRakePrice);
            var entity = new DallyStatistics()
            {
                Id = GuidGenerator.Create(),
                CreationTime = today,
                AccumulatedReceipts = accumulatedReceipts ?? 0,
                AccumulatedIncome = accumulatedIncome ?? 0,
                IncomeYesterday = yesterdayIncome ?? 0,
                ReceiptsYesterday = receiptsYesterday ?? 0,
                AccumulatedOrders = accumulatedOrders,
                OrdersNumYesterday = ordersNumYesterday,
                YesterdaySuccess = yesterdaySuccess,
                YesterdayFail = yesterdayFail,
                AccumulatedUsers = accumulatedUsers,
                YesterdayActiveUsers = yesterdayActiveUsers,
                ChannelId = channleId,
                AccumulatedChannlesRakePrice = accumulatedChannlesRakePrice,
                Date = today.AddDays(-1)
            };
            await _dallyStatisticsRepository.InsertAsync(entity);
            return entity;
        }
    }
}