YD_Event.Admin/YD_Event.Application/Event/EventRegistrationService.cs
2026-04-13 13:23:00 +08:00

329 lines
14 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 YD_Event.Application.Event.Dtos;
using YD_Event.Application.Auth;
using YD_Event.Core.Entities;
using MiniExcelLibs;
namespace YD_Event.Application.Event;
/// <summary>
/// 报名管理服务
/// </summary>
public class EventRegistrationService : BaseService<EventRegistration>, ITransient
{
private readonly ISqlSugarRepository<EventRegistration> _repository;
private readonly ISqlSugarRepository<EventRegistrationItem> _itemRepository;
private readonly ISqlSugarRepository<EventRegistrationPerson> _personRepository;
private readonly ISqlSugarRepository<EventRegistrationPayment> _paymentRepository;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Order> _orderRepository;
private readonly AuthManager _authManager;
public EventRegistrationService(
ISqlSugarRepository<EventRegistration> repository,
ISqlSugarRepository<EventRegistrationItem> itemRepository,
ISqlSugarRepository<EventRegistrationPerson> personRepository,
ISqlSugarRepository<EventRegistrationPayment> paymentRepository,
ISqlSugarRepository<YD_Event.Core.Entities.Order> orderRepository,
AuthManager authManager) : base(repository)
{
_repository = repository;
_itemRepository = itemRepository;
_personRepository = personRepository;
_paymentRepository = paymentRepository;
_orderRepository = orderRepository;
_authManager = authManager;
}
/// <summary>
/// 分页查询报名
/// </summary>
[DisplayName("分页查询报名")]
public async Task<PageResult<RegistrationListOutput>> Page(RegistrationQueryInput input)
{
var query = _repository.AsQueryable()
.WhereIF(input.EventId.HasValue, x => x.EventId == input.EventId)
.WhereIF(input.RegistrationMode.HasValue, x => x.RegistrationMode == input.RegistrationMode)
.WhereIF(!string.IsNullOrWhiteSpace(input.UnitName), x => x.TeamName.Contains(input.UnitName))
.WhereIF(!string.IsNullOrWhiteSpace(input.UserName), x => x.ContactName.Contains(input.UserName))
.WhereIF(!string.IsNullOrWhiteSpace(input.ContactPhone), x => x.ContactPhone.Contains(input.ContactPhone))
.WhereIF(input.IsUploadMaterial.HasValue, x => (input.IsUploadMaterial.Value ? !string.IsNullOrEmpty(x.MaterialUrl) : string.IsNullOrEmpty(x.MaterialUrl)))
.WhereIF(input.PaymentMethod.HasValue, x => x.PaymentMethod == input.PaymentMethod)
.WhereIF(input.PaymentStatus.HasValue, x => x.PaymentStatus == input.PaymentStatus)
.WhereIF(input.RegistrationTimeStart.HasValue, x => x.RegistrationTime >= input.RegistrationTimeStart)
.WhereIF(input.RegistrationTimeEnd.HasValue, x => x.RegistrationTime <= input.RegistrationTimeEnd)
.OrderByDescending(x => x.RegistrationTime)
.Select(x => new RegistrationListOutput
{
Id = x.Id,
RegistrationMode = x.RegistrationMode,
UnitName = x.TeamName,
ContactName = x.ContactName,
ContactPhone = x.ContactPhone,
TotalPersonCount = x.TotalPersonCount,
IsUploadMaterial = !string.IsNullOrEmpty(x.MaterialUrl),
PaymentMethod = x.PaymentMethod,
PaymentMethodType = x.PaymentMethodType,
OrderNo = x.OrderNo,
TotalAmount = x.TotalAmount,
PaymentStatus = x.PaymentStatus,
PaymentProofUrl = x.PaymentProofUrl,
RegistrationTime = x.RegistrationTime
});
var result = await query.ToPagedListAsync(input);
// 填充下拉详情
if (result.Rows.Any())
{
var regIds = result.Rows.Select(x => x.Id).ToList();
var items = await _itemRepository.GetListAsync(x => regIds.Contains(x.RegistrationId));
// 使用关联查询获取报名人员及其关联的用户信息
var persons = await _personRepository.AsQueryable()
.Includes(p => p.User) // 关联查询用户信息
.Where(x => regIds.Contains(x.RegistrationId))
.ToListAsync();
foreach (var dto in result.Rows)
{
var myItems = items.Where(x => x.RegistrationId == dto.Id).ToList();
dto.Items = new List<RegistrationItemDetailDto>();
foreach (var item in myItems)
{
var myPersons = persons.Where(p => p.RegistrationItemId == item.Id).ToList();
// 构造参与人信息字符串,可以使用关联的 User 信息
var personInfo = string.Join(";", myPersons.Select(p =>
{
// 将性别转换为中文显示
var genderText = p.Gender switch
{
YD_Event.Core.Enum.Gender.Male => "男",
YD_Event.Core.Enum.Gender.Female => "女",
_ => "未知"
};
// 如果有关联的用户信息,可以使用更完整的信息
if (p.User != null)
{
return $"{p.Name}({p.User.Mobile})/{genderText}/{p.Age}";
}
return $"{p.Name}/{genderText}/{p.Age}/{p.IdCard}";
}));
if (personInfo.Length > 100) personInfo = personInfo.Substring(0, 97) + "..."; // 截断
var detail = new RegistrationItemDetailDto
{
ProjectName = item.ProjectName,
GroupName = item.GroupName,
ParticipantInfo = personInfo
};
dto.Items.Add(detail);
}
// 设置领队信息和教练信息
var regPersons = persons.Where(p => p.RegistrationId == dto.Id).ToList();
var leaders = regPersons.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Leader).ToList();
var coaches = regPersons.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Coach).ToList();
dto.TeamLeaderInfo = leaders.Any()
? string.Join(";", leaders.Select(l => $"{l.Name}({l.Phone})"))
: null;
dto.CoachInfo = coaches.Any()
? string.Join(";", coaches.Select(c => $"{c.Name}({c.Phone})"))
: null;
}
}
return result;
}
/// <summary>
/// 批量审核
/// </summary>
[UnitOfWork]
[DisplayName("批量审核")]
public async Task BatchAudit(BatchAuditInput input)
{
if (input.Ids == null || !input.Ids.Any()) return;
// 更新报名记录的支付状态
await _repository.UpdateAsync(x => new EventRegistration
{
PaymentStatus = input.PaymentStatus,
ReviewRemark = input.ReviewRemark,
ReviewTime = DateTime.Now
}, x => input.Ids.Contains(x.Id));
// 如果审核通过(PaymentStatus = 1),同步更新相关订单的状态为已支付
if (input.PaymentStatus == 1)
{
// 获取需要更新的报名记录
var registrations = await _repository.GetListAsync(x => input.Ids.Contains(x.Id));
// 提取所有订单号
var orderNos = registrations
.Where(r => !string.IsNullOrEmpty(r.OrderNo))
.Select(r => r.OrderNo)
.ToList();
if (orderNos.Any())
{
var now = DateTime.Now;
// 更新相关订单的状态为已支付
await _orderRepository.UpdateAsync(x => new YD_Event.Core.Entities.Order
{
OrderStatus = YD_Event.Core.Enum.OrderStatus.Paid,
PaymentTime = now,
UpdatedTime = now,
UpdatedUserId = _authManager.UserId
}, x => orderNos.Contains(x.OrderNo));
}
}
}
/// <summary>
/// 导出报名
/// </summary>
[DisplayName("导出报名")]
public async Task<byte[]> Export(RegistrationQueryInput input)
{
var list = await _repository.AsQueryable()
.WhereIF(input.EventId.HasValue, x => x.EventId == input.EventId)
.WhereIF(input.RegistrationMode.HasValue, x => x.RegistrationMode == input.RegistrationMode)
.WhereIF(!string.IsNullOrWhiteSpace(input.UnitName), x => x.TeamName.Contains(input.UnitName))
.WhereIF(!string.IsNullOrWhiteSpace(input.UserName), x => x.ContactName.Contains(input.UserName))
.WhereIF(!string.IsNullOrWhiteSpace(input.ContactPhone), x => x.ContactPhone.Contains(input.ContactPhone))
.WhereIF(input.PaymentStatus.HasValue, x => x.PaymentStatus == input.PaymentStatus)
.Select(x => new
{
x.RegistrationMode,
x.TeamName,
x.ContactName,
x.ContactPhone,
x.TotalPersonCount,
x.PaymentMethod,
x.TotalAmount,
x.PaymentStatus,
x.RegistrationTime
})
.ToListAsync();
using var stream = new MemoryStream();
stream.SaveAs(list);
return stream.ToArray();
}
/// <summary>
/// 获取素材下载链接
/// </summary>
[DisplayName("获取素材下载链接")]
public async Task<List<string>> MaterialUrls(List<long> ids)
{
if (ids == null || !ids.Any()) return new List<string>();
return await _repository.AsQueryable()
.Where(x => ids.Contains(x.Id) && !string.IsNullOrEmpty(x.MaterialUrl))
.Select(x => x.MaterialUrl)
.ToListAsync();
}
/// <summary>
/// 单条支付审核
/// </summary>
[UnitOfWork]
[DisplayName("单条支付审核")]
public async Task PaymentAudit(PaymentAuditInput input)
{
var registration = await _repository.GetByIdAsync(input.RegistrationId);
if (registration == null) throw Oops.Bah("报名记录不存在");
if (registration.PaymentStatus != 0)
{
throw Oops.Bah("该记录已完成支付审核,无需重复操作");
}
var now = DateTime.Now;
registration.PaymentStatus = input.PaymentStatus;
registration.ReviewRemark = input.ReviewRemark;
registration.ReviewTime = now;
registration.Reviewer = _authManager.Account;
registration.UpdatedTime = now;
registration.UpdatedUserId = _authManager.UserId;
if (input.PaymentStatus == 1)
{
registration.PaymentTime = now;
}
await _repository.UpdateAsync(registration);
// 如果审核通过(PaymentStatus = 1),同步更新相关订单的状态为已支付
if (input.PaymentStatus == 1 && !string.IsNullOrEmpty(registration.OrderNo))
{
// 更新相关订单的状态为已支付
await _orderRepository.UpdateAsync(x => new YD_Event.Core.Entities.Order
{
OrderStatus = YD_Event.Core.Enum.OrderStatus.Paid,
PaymentTime = now,
UpdatedTime = now,
UpdatedUserId = _authManager.UserId
}, x => x.OrderNo == registration.OrderNo);
}
}
/// <summary>
/// 批量支付审核
/// </summary>
[UnitOfWork]
[DisplayName("批量支付审核")]
public async Task BatchPaymentAudit(BatchPaymentAuditInput input)
{
if (input.Ids == null || !input.Ids.Any()) return;
var registrations = await _repository.GetListAsync(x => input.Ids.Contains(x.Id));
if (!registrations.Any()) throw Oops.Bah("未找到有效的报名记录");
var invalidRegistrations = registrations
.Where(r => r.PaymentStatus != 0)
.ToList();
if (invalidRegistrations.Any())
{
throw Oops.Bah("存在非待审核状态的记录,无法进行支付审核");
}
var now = DateTime.Now;
await _repository.UpdateAsync(x => new EventRegistration
{
PaymentStatus = input.PaymentStatus,
ReviewRemark = input.ReviewRemark,
ReviewTime = now,
Reviewer = _authManager.Account,
UpdatedTime = now,
UpdatedUserId = _authManager.UserId,
PaymentTime = input.PaymentStatus == 1 ? now : x.PaymentTime
}, x => input.Ids.Contains(x.Id));
// 如果审核通过(PaymentStatus = 1),同步更新相关订单的状态为已支付
if (input.PaymentStatus == 1)
{
// 提取所有订单号
var orderNos = registrations
.Where(r => !string.IsNullOrEmpty(r.OrderNo))
.Select(r => r.OrderNo)
.ToList();
if (orderNos.Any())
{
// 更新相关订单的状态为已支付
await _orderRepository.UpdateAsync(x => new YD_Event.Core.Entities.Order
{
OrderStatus = YD_Event.Core.Enum.OrderStatus.Paid,
PaymentTime = now,
UpdatedTime = now,
UpdatedUserId = _authManager.UserId
}, x => orderNos.Contains(x.OrderNo));
}
}
}
}