using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Tnsu.ApprovalRoute.Domain.Entities; using Tnsu.ApprovalRoute.Infrastructure.Persistence; using Tnsu.ApprovalRoute.Infrastructure.SharePoint; namespace Tnsu.ApprovalRoute.Application.ListPartitioning; /// /// Наполнение реестра партиций. Вынесено отдельно, потому что нужно и читающему /// эндпоинту, и фоновой задаче: реестр появился позже самих списков, и любой из них /// может встретить тип заявок, которого в реестре ещё нет. /// public sealed class ListPartitionRegistry( ApprovalRouteDbContext db, ISharePointClient sharePoint, ILogger logger) { /// /// Гарантирует, что текущая партиция типа заявок есть в реестре, и возвращает её строку. /// /// Реестр самозаполняющийся: до этой фичи списки жили только в /// RequestType.ListId, и переключить список руками в админке можно и сейчас. /// Поэтому неизвестный реестру ListId дописывается следующим номером, а не /// считается ошибкой. /// /// Требует заполненного ListId — вызывающая сторона это проверяет. /// public async Task EnsureCurrentRegisteredAsync( RequestType requestType, CancellationToken cancellationToken) { var series = await db.RequestListPartitions .Where(x => x.RequestTypeId == requestType.Id) .ToListAsync(cancellationToken); var existing = series.FirstOrDefault(x => x.ListId == requestType.ListId); if (existing is not null) return existing; var entity = new RequestListPartition { RequestTypeId = requestType.Id, Number = series.Count == 0 ? 1 : series.Max(x => x.Number) + 1, ListId = requestType.ListId!, Title = await TryGetTitleAsync(requestType.SiteUrl!, requestType.ListId!, cancellationToken), CreatedAt = DateTimeOffset.UtcNow }; db.RequestListPartitions.Add(entity); await db.SaveChangesAsync(cancellationToken); logger.LogInformation( "Список {ListId} типа заявок {RequestTypeId} добавлен в реестр под номером {Number}.", entity.ListId, requestType.Id, entity.Number); return entity; } // Заголовок нужен только для отображения в админке/портале — из-за его // отсутствия регистрация партиции падать не должна. private async Task TryGetTitleAsync(string siteUrl, string listId, CancellationToken cancellationToken) { try { return await sharePoint.GetListTitleAsync(siteUrl, listId, cancellationToken); } catch (Exception ex) { logger.LogWarning(ex, "Не удалось прочитать заголовок списка {ListId}.", listId); return null; } } }