425 lines
14 KiB
C#
425 lines
14 KiB
C#
using HoneyBox.Admin.Business.Models;
|
|
using HoneyBox.Admin.Business.Models.Finance;
|
|
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 FinanceService : IFinanceService
|
|
{
|
|
private readonly HoneyBoxDbContext _dbContext;
|
|
private readonly ILogger<FinanceService> _logger;
|
|
|
|
public FinanceService(HoneyBoxDbContext dbContext, ILogger<FinanceService> logger)
|
|
{
|
|
_dbContext = dbContext;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取消费排行榜
|
|
/// </summary>
|
|
public async Task<PagedResult<ConsumptionRankingResponse>> GetConsumptionRankingAsync(FinanceQueryRequest request)
|
|
{
|
|
// 基于订单表统计用户消费
|
|
var query = _dbContext.Orders
|
|
.Where(o => o.Status == 1) // 已支付订单
|
|
.GroupBy(o => o.UserId)
|
|
.Select(g => new
|
|
{
|
|
UserId = g.Key,
|
|
TotalConsumption = g.Sum(o => o.Price),
|
|
WeChatPayment = g.Sum(o => o.Price - o.UseMoney - o.UseIntegral - o.UseScore),
|
|
BalancePayment = g.Sum(o => o.UseMoney),
|
|
IntegralPayment = g.Sum(o => o.UseIntegral)
|
|
});
|
|
|
|
// 日期过滤
|
|
if (request.StartDate.HasValue)
|
|
{
|
|
var startDate = request.StartDate.Value.Date;
|
|
query = _dbContext.Orders
|
|
.Where(o => o.Status == 1 && o.CreatedAt >= startDate)
|
|
.GroupBy(o => o.UserId)
|
|
.Select(g => new
|
|
{
|
|
UserId = g.Key,
|
|
TotalConsumption = g.Sum(o => o.Price),
|
|
WeChatPayment = g.Sum(o => o.Price - o.UseMoney - o.UseIntegral - o.UseScore),
|
|
BalancePayment = g.Sum(o => o.UseMoney),
|
|
IntegralPayment = g.Sum(o => o.UseIntegral)
|
|
});
|
|
}
|
|
|
|
if (request.EndDate.HasValue)
|
|
{
|
|
var endDate = request.EndDate.Value.Date.AddDays(1);
|
|
query = _dbContext.Orders
|
|
.Where(o => o.Status == 1 && o.CreatedAt < endDate)
|
|
.GroupBy(o => o.UserId)
|
|
.Select(g => new
|
|
{
|
|
UserId = g.Key,
|
|
TotalConsumption = g.Sum(o => o.Price),
|
|
WeChatPayment = g.Sum(o => o.Price - o.UseMoney - o.UseIntegral - o.UseScore),
|
|
BalancePayment = g.Sum(o => o.UseMoney),
|
|
IntegralPayment = g.Sum(o => o.UseIntegral)
|
|
});
|
|
}
|
|
|
|
// 按消费金额降序排序
|
|
var orderedQuery = query.OrderByDescending(x => x.TotalConsumption);
|
|
|
|
var total = await query.CountAsync();
|
|
var items = await orderedQuery
|
|
.Skip((request.Page - 1) * request.PageSize)
|
|
.Take(request.PageSize)
|
|
.ToListAsync();
|
|
|
|
// 获取用户信息
|
|
var userIds = items.Select(x => x.UserId).ToList();
|
|
var users = await _dbContext.Users
|
|
.Where(u => userIds.Contains(u.Id))
|
|
.ToDictionaryAsync(u => u.Id);
|
|
|
|
var result = items.Select(x =>
|
|
{
|
|
users.TryGetValue(x.UserId, out var user);
|
|
return new ConsumptionRankingResponse
|
|
{
|
|
UserId = x.UserId,
|
|
Uid = user?.Uid,
|
|
Nickname = user?.Nickname,
|
|
Avatar = user?.HeadImg,
|
|
Mobile = user?.Mobile,
|
|
TotalConsumption = x.TotalConsumption,
|
|
WeChatPayment = x.WeChatPayment,
|
|
BalancePayment = x.BalancePayment,
|
|
IntegralPayment = x.IntegralPayment,
|
|
CreatedAt = user?.CreatedAt ?? DateTime.MinValue
|
|
};
|
|
}).ToList();
|
|
|
|
return new PagedResult<ConsumptionRankingResponse>
|
|
{
|
|
List = result,
|
|
Total = total,
|
|
Page = request.Page,
|
|
PageSize = request.PageSize
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取余额明细
|
|
/// </summary>
|
|
public async Task<PagedResult<BalanceDetailResponse>> GetBalanceDetailsAsync(FinanceQueryRequest request)
|
|
{
|
|
var query = _dbContext.ProfitMoneys.AsQueryable();
|
|
|
|
// 用户ID过滤
|
|
if (request.UserId.HasValue)
|
|
{
|
|
query = query.Where(p => p.UserId == request.UserId.Value);
|
|
}
|
|
|
|
// 手机号过滤 - 需要关联用户表
|
|
if (!string.IsNullOrWhiteSpace(request.Mobile))
|
|
{
|
|
var userIds = await _dbContext.Users
|
|
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
|
|
.Select(u => u.Id)
|
|
.ToListAsync();
|
|
query = query.Where(p => userIds.Contains(p.UserId));
|
|
}
|
|
|
|
// 日期过滤
|
|
if (request.StartDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt >= request.StartDate.Value.Date);
|
|
}
|
|
if (request.EndDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt < request.EndDate.Value.Date.AddDays(1));
|
|
}
|
|
|
|
var total = await query.CountAsync();
|
|
var items = await query
|
|
.OrderByDescending(p => p.Id)
|
|
.Skip((request.Page - 1) * request.PageSize)
|
|
.Take(request.PageSize)
|
|
.ToListAsync();
|
|
|
|
// 获取用户信息
|
|
var userIds2 = items.Select(x => x.UserId).Distinct().ToList();
|
|
var users = await _dbContext.Users
|
|
.Where(u => userIds2.Contains(u.Id))
|
|
.ToDictionaryAsync(u => u.Id);
|
|
|
|
var result = items.Select(x =>
|
|
{
|
|
users.TryGetValue(x.UserId, out var user);
|
|
return new BalanceDetailResponse
|
|
{
|
|
Id = x.Id,
|
|
UserId = x.UserId,
|
|
Uid = user?.Uid,
|
|
Nickname = user?.Nickname,
|
|
Mobile = user?.Mobile,
|
|
ChangeMoney = x.ChangeMoney,
|
|
Money = x.Money,
|
|
Type = x.Type,
|
|
Content = x.Content,
|
|
CreatedAt = x.CreatedAt
|
|
};
|
|
}).ToList();
|
|
|
|
return new PagedResult<BalanceDetailResponse>
|
|
{
|
|
List = result,
|
|
Total = total,
|
|
Page = request.Page,
|
|
PageSize = request.PageSize
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取积分明细
|
|
/// </summary>
|
|
public async Task<PagedResult<IntegralDetailResponse>> GetIntegralDetailsAsync(FinanceQueryRequest request)
|
|
{
|
|
var query = _dbContext.ProfitIntegrals.AsQueryable();
|
|
|
|
// 用户ID过滤
|
|
if (request.UserId.HasValue)
|
|
{
|
|
query = query.Where(p => p.UserId == request.UserId.Value);
|
|
}
|
|
|
|
// 手机号过滤
|
|
if (!string.IsNullOrWhiteSpace(request.Mobile))
|
|
{
|
|
var userIds = await _dbContext.Users
|
|
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
|
|
.Select(u => u.Id)
|
|
.ToListAsync();
|
|
query = query.Where(p => userIds.Contains(p.UserId));
|
|
}
|
|
|
|
// 日期过滤
|
|
if (request.StartDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt >= request.StartDate.Value.Date);
|
|
}
|
|
if (request.EndDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt < request.EndDate.Value.Date.AddDays(1));
|
|
}
|
|
|
|
var total = await query.CountAsync();
|
|
var items = await query
|
|
.OrderByDescending(p => p.Id)
|
|
.Skip((request.Page - 1) * request.PageSize)
|
|
.Take(request.PageSize)
|
|
.ToListAsync();
|
|
|
|
// 获取用户信息
|
|
var userIds2 = items.Select(x => x.UserId).Distinct().ToList();
|
|
var users = await _dbContext.Users
|
|
.Where(u => userIds2.Contains(u.Id))
|
|
.ToDictionaryAsync(u => u.Id);
|
|
|
|
var result = items.Select(x =>
|
|
{
|
|
users.TryGetValue(x.UserId, out var user);
|
|
return new IntegralDetailResponse
|
|
{
|
|
Id = x.Id,
|
|
UserId = x.UserId,
|
|
Uid = user?.Uid,
|
|
Nickname = user?.Nickname,
|
|
Mobile = user?.Mobile,
|
|
ChangeMoney = x.ChangeMoney,
|
|
Money = x.Money,
|
|
Type = x.Type,
|
|
Content = x.Content,
|
|
CreatedAt = x.CreatedAt
|
|
};
|
|
}).ToList();
|
|
|
|
return new PagedResult<IntegralDetailResponse>
|
|
{
|
|
List = result,
|
|
Total = total,
|
|
Page = request.Page,
|
|
PageSize = request.PageSize
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取钻石明细
|
|
/// </summary>
|
|
public async Task<PagedResult<ScoreDetailResponse>> GetScoreDetailsAsync(FinanceQueryRequest request)
|
|
{
|
|
var query = _dbContext.ProfitScores.AsQueryable();
|
|
|
|
// 用户ID过滤
|
|
if (request.UserId.HasValue)
|
|
{
|
|
query = query.Where(p => p.UserId == request.UserId.Value);
|
|
}
|
|
|
|
// 手机号过滤
|
|
if (!string.IsNullOrWhiteSpace(request.Mobile))
|
|
{
|
|
var userIds = await _dbContext.Users
|
|
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
|
|
.Select(u => u.Id)
|
|
.ToListAsync();
|
|
query = query.Where(p => userIds.Contains(p.UserId));
|
|
}
|
|
|
|
// 日期过滤
|
|
if (request.StartDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt >= request.StartDate.Value.Date);
|
|
}
|
|
if (request.EndDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt < request.EndDate.Value.Date.AddDays(1));
|
|
}
|
|
|
|
var total = await query.CountAsync();
|
|
var items = await query
|
|
.OrderByDescending(p => p.Id)
|
|
.Skip((request.Page - 1) * request.PageSize)
|
|
.Take(request.PageSize)
|
|
.ToListAsync();
|
|
|
|
// 获取用户信息
|
|
var userIds2 = items.Select(x => x.UserId).Distinct().ToList();
|
|
var users = await _dbContext.Users
|
|
.Where(u => userIds2.Contains(u.Id))
|
|
.ToDictionaryAsync(u => u.Id);
|
|
|
|
var result = items.Select(x =>
|
|
{
|
|
users.TryGetValue(x.UserId, out var user);
|
|
return new ScoreDetailResponse
|
|
{
|
|
Id = x.Id,
|
|
UserId = x.UserId,
|
|
Uid = user?.Uid,
|
|
Nickname = user?.Nickname,
|
|
Mobile = user?.Mobile,
|
|
ChangeMoney = x.ChangeMoney,
|
|
Money = x.Money,
|
|
Type = x.Type,
|
|
Content = x.Content,
|
|
CreatedAt = x.CreatedAt
|
|
};
|
|
}).ToList();
|
|
|
|
return new PagedResult<ScoreDetailResponse>
|
|
{
|
|
List = result,
|
|
Total = total,
|
|
Page = request.Page,
|
|
PageSize = request.PageSize
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取充值记录
|
|
/// </summary>
|
|
public async Task<PagedResult<RechargeRecordResponse>> GetRechargeRecordsAsync(FinanceQueryRequest request)
|
|
{
|
|
var query = _dbContext.ProfitPays.AsQueryable();
|
|
|
|
// 用户ID过滤
|
|
if (request.UserId.HasValue)
|
|
{
|
|
query = query.Where(p => p.UserId == request.UserId.Value);
|
|
}
|
|
|
|
// 手机号过滤
|
|
if (!string.IsNullOrWhiteSpace(request.Mobile))
|
|
{
|
|
var userIds = await _dbContext.Users
|
|
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
|
|
.Select(u => u.Id)
|
|
.ToListAsync();
|
|
query = query.Where(p => userIds.Contains(p.UserId));
|
|
}
|
|
|
|
// 日期过滤
|
|
if (request.StartDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt >= request.StartDate.Value.Date);
|
|
}
|
|
if (request.EndDate.HasValue)
|
|
{
|
|
query = query.Where(p => p.CreatedAt < request.EndDate.Value.Date.AddDays(1));
|
|
}
|
|
|
|
var total = await query.CountAsync();
|
|
var items = await query
|
|
.OrderByDescending(p => p.Id)
|
|
.Skip((request.Page - 1) * request.PageSize)
|
|
.Take(request.PageSize)
|
|
.ToListAsync();
|
|
|
|
// 获取用户信息
|
|
var userIds2 = items.Select(x => x.UserId).Distinct().ToList();
|
|
var users = await _dbContext.Users
|
|
.Where(u => userIds2.Contains(u.Id))
|
|
.ToDictionaryAsync(u => u.Id);
|
|
|
|
var result = items.Select(x =>
|
|
{
|
|
users.TryGetValue(x.UserId, out var user);
|
|
return new RechargeRecordResponse
|
|
{
|
|
Id = x.Id,
|
|
UserId = x.UserId,
|
|
Uid = user?.Uid,
|
|
Nickname = user?.Nickname,
|
|
Mobile = user?.Mobile,
|
|
OrderNum = x.OrderNum,
|
|
ChangeMoney = x.ChangeMoney,
|
|
Content = x.Content,
|
|
PayType = x.PayType,
|
|
PayTypeName = GetPayTypeName(x.PayType),
|
|
CreatedAt = x.CreatedAt
|
|
};
|
|
}).ToList();
|
|
|
|
return new PagedResult<RechargeRecordResponse>
|
|
{
|
|
List = result,
|
|
Total = total,
|
|
Page = request.Page,
|
|
PageSize = request.PageSize
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取支付类型名称
|
|
/// </summary>
|
|
private static string GetPayTypeName(byte payType)
|
|
{
|
|
return payType switch
|
|
{
|
|
0 => "微信支付",
|
|
1 => "支付宝",
|
|
2 => "余额支付",
|
|
3 => "积分支付",
|
|
_ => "其他"
|
|
};
|
|
}
|
|
}
|