133 lines
5.8 KiB
C#
133 lines
5.8 KiB
C#
using YD_Event.Application.Client.Dtos;
|
||
using YD_Event.Application.Event;
|
||
|
||
namespace YD_Event.Application.Client;
|
||
|
||
/// <summary>从秩序册实时生成检录项目、组别和列对象。</summary>
|
||
public class CheckinScheduleService : ITransient
|
||
{
|
||
private readonly ISqlSugarRepository<EventInfo> _eventRepository;
|
||
private readonly ISqlSugarRepository<EventRegistrationPerson> _personRepository;
|
||
private readonly EventArrangementService _arrangementService;
|
||
|
||
public CheckinScheduleService(
|
||
ISqlSugarRepository<EventInfo> eventRepository,
|
||
ISqlSugarRepository<EventRegistrationPerson> personRepository,
|
||
EventArrangementService arrangementService)
|
||
{
|
||
_eventRepository = eventRepository;
|
||
_personRepository = personRepository;
|
||
_arrangementService = arrangementService;
|
||
}
|
||
|
||
public async Task<CheckinEventOptionsDto> 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<EventRegistrationPerson>()
|
||
: await _personRepository.AsQueryable()
|
||
.Where(x => personIds.Contains(x.Id) && !x.DeleteMark && x.PersonType == PersonType.Athlete)
|
||
.ToListAsync();
|
||
var personMap = persons.ToDictionary(x => x.Id);
|
||
|
||
// 团队项目沿用报名项目作为检录单位;个人项目追加报名人员 ID,
|
||
// 避免单位账号在同一报名项目下填报多人时共用同一个检录键。
|
||
var units = rows.Select((row, index) => new CheckinOrderBookUnitDto
|
||
{
|
||
UnitKey = BuildUnitKey(row.EventProjectId, row.RegistrationItemId,
|
||
row.IsTeamProject ? null : row.RegistrationPersonIds.SingleOrDefault()),
|
||
IsTeamProject = row.IsTeamProject,
|
||
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<CheckinSessionOptionDto>(),
|
||
Rounds = new List<CheckinRoundOptionDto>()
|
||
};
|
||
}
|
||
|
||
public static CheckinOrderBookUnitDto ResolveUnit(CheckinEventOptionsDto options, string unitKey)
|
||
{
|
||
var unit = options.Units.FirstOrDefault(x => x.UnitKey == unitKey);
|
||
return unit ?? throw Oops.Bah("所选检录对象不属于当前赛事秩序册");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成检录对象唯一键。团队项目不传人员 ID,个人项目必须传入人员 ID。
|
||
/// </summary>
|
||
public static string BuildUnitKey(
|
||
long eventProjectId, long registrationItemId, long? registrationPersonId = null)
|
||
{
|
||
var key = $"EP{eventProjectId}-RI{registrationItemId}";
|
||
return registrationPersonId.HasValue && registrationPersonId.Value > 0
|
||
? $"{key}-RP{registrationPersonId.Value}"
|
||
: key;
|
||
}
|
||
|
||
private static string FormatBibNo(long personId)
|
||
{
|
||
var value = personId.ToString();
|
||
return value.Length > 6 ? value[^6..] : value.PadLeft(6, '0');
|
||
}
|
||
}
|