using YD_Event.Application.Client.Dtos;
using YD_Event.Application.Event;
namespace YD_Event.Application.Client;
/// 从秩序册实时生成检录项目、组别和列对象。
public class CheckinScheduleService : ITransient
{
private readonly ISqlSugarRepository _eventRepository;
private readonly ISqlSugarRepository _personRepository;
private readonly EventArrangementService _arrangementService;
public CheckinScheduleService(
ISqlSugarRepository eventRepository,
ISqlSugarRepository personRepository,
EventArrangementService arrangementService)
{
_eventRepository = eventRepository;
_personRepository = personRepository;
_arrangementService = arrangementService;
}
public async Task GetOptionsAsync(long eventId)
{
var evt = await _eventRepository.GetFirstAsync(x =>
x.Id == eventId && !x.DeleteMark && x.Status == AvailabilityStatus.Enable);
if (evt == null) throw Oops.Bah("赛事不存在或已停用");
// Preview 的每一行就是秩序册中的一列:个人项目一人,团队项目可以多人。
var rows = await _arrangementService.Preview(eventId);
if (rows.Count == 0) throw Oops.Bah("当前赛事尚未生成有效秩序册,不能创建检录任务");
var personIds = rows.SelectMany(x => x.RegistrationPersonIds).Distinct().ToList();
var persons = personIds.Count == 0
? new List()
: await _personRepository.AsQueryable()
.Where(x => personIds.Contains(x.Id) && !x.DeleteMark && x.PersonType == PersonType.Athlete)
.ToListAsync();
var personMap = persons.ToDictionary(x => x.Id);
var units = rows.Select((row, index) => new CheckinOrderBookUnitDto
{
UnitKey = BuildUnitKey(row.EventProjectId, row.RegistrationItemId),
Order = index + 1,
SessionIndex = row.SessionIndex,
VenueIndex = row.VenueIndex,
VenueName = $"{row.VenueIndex}号场地",
EventProjectId = row.EventProjectId,
ProjectId = row.ProjectId,
ProjectName = row.ProjectName,
GroupId = row.EventProjectGroupId,
GroupName = row.GroupName,
RegistrationItemId = row.RegistrationItemId,
TeamName = row.TeamName ?? string.Empty,
UnitName = row.UnitName ?? string.Empty,
RegistrationPersonIds = row.RegistrationPersonIds.Distinct().ToList(),
Athletes = row.RegistrationPersonIds.Distinct()
.Where(personMap.ContainsKey)
.Select(personId =>
{
var person = personMap[personId];
return new CheckinAthleteDto
{
Id = person.Id,
UserId = person.UserId,
BibNo = FormatBibNo(person.Id),
Name = person.Name,
TeamName = row.TeamName ?? string.Empty
};
}).ToList()
}).ToList();
var projects = units.GroupBy(x => new { x.EventProjectId, x.ProjectId, x.ProjectName })
.Select((project, projectIndex) => new CheckinProjectOptionDto
{
EventProjectId = project.Key.EventProjectId,
ProjectId = project.Key.ProjectId,
ProjectName = project.Key.ProjectName,
Order = projectIndex + 1,
Groups = project.Where(x => x.GroupId.HasValue)
.GroupBy(x => new { Id = x.GroupId!.Value, x.GroupName })
.Select((group, groupIndex) => new CheckinGroupOptionDto
{
Id = group.Key.Id,
EventProjectId = project.Key.EventProjectId,
ProjectId = project.Key.ProjectId,
ProjectName = project.Key.ProjectName,
GroupName = group.Key.GroupName,
Order = groupIndex + 1
}).ToList()
}).ToList();
return new CheckinEventOptionsDto
{
EventId = evt.Id,
EventName = evt.EventName,
Projects = projects,
Units = units,
// 兼容旧调用方:Sessions 不再是检录对象。
Sessions = new List(),
Rounds = new List()
};
}
public static CheckinOrderBookUnitDto ResolveUnit(CheckinEventOptionsDto options, string unitKey)
{
var unit = options.Units.FirstOrDefault(x => x.UnitKey == unitKey);
return unit ?? throw Oops.Bah("所选检录对象不属于当前赛事秩序册");
}
public static string BuildUnitKey(long eventProjectId, long registrationItemId) =>
$"EP{eventProjectId}-RI{registrationItemId}";
private static string FormatBibNo(long personId)
{
var value = personId.ToString();
return value.Length > 6 ? value[^6..] : value.PadLeft(6, '0');
}
}