Update scheduling parameters and refactor channel endpoints: extend HorizonDays to 7 and RetentionDays to 90 in appsettings.json. Consolidate channel-related endpoint logic by removing obsolete files and enhancing the ShowEndpoints with audience and genre management capabilities. Improve error handling and streamline command handlers for channel operations.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TeleWave.Application.Common.Interfaces;
|
||||
using TeleWave.Application.Common.Models;
|
||||
using TeleWave.Domain.Programming;
|
||||
|
||||
namespace TeleWave.Application.Programming.Templates;
|
||||
|
||||
/// <summary>
|
||||
/// Общая часть создания и правки слота: проверки, которые нельзя доверить валидатору, потому что
|
||||
/// им нужны соседние слоты и справочник групп.
|
||||
/// </summary>
|
||||
public sealed class SlotWriter(IAppDbContext dbContext)
|
||||
{
|
||||
/// <summary>
|
||||
/// Проверяет вход и применяет его к слоту. <paramref name="slot"/> = null — проверка перед
|
||||
/// созданием.
|
||||
/// </summary>
|
||||
public async Task<Result> ApplyAsync(
|
||||
GridLayer layer,
|
||||
Slot? slot,
|
||||
SlotInput input,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// Перекрытие внутри слоя запрещено: два слота на одну минуту сделали бы выбор неоднозначным.
|
||||
if (
|
||||
layer.HasOverlap(
|
||||
input.Weekday,
|
||||
input.TargetStart,
|
||||
input.TargetDurationMinutes,
|
||||
slot?.Id
|
||||
)
|
||||
)
|
||||
return Result.Failure(TemplateErrors.SlotsOverlap);
|
||||
|
||||
if (input.SlotKind == SlotKind.Content)
|
||||
{
|
||||
if (input.GroupId is not { } groupId)
|
||||
return Result.Failure(TemplateErrors.GroupRequired);
|
||||
|
||||
if (!await dbContext.Groups.AnyAsync(g => g.Id == groupId, cancellationToken))
|
||||
return Result.Failure(TemplateErrors.GroupNotFound);
|
||||
}
|
||||
|
||||
if (input.SlotKind == SlotKind.Repeat && input.RepeatSource is null)
|
||||
return Result.Failure(TemplateErrors.RepeatSourceRequired);
|
||||
|
||||
var target =
|
||||
slot
|
||||
?? layer.AddSlot(
|
||||
input.Title,
|
||||
input.TargetStart,
|
||||
input.TargetDurationMinutes,
|
||||
input.Daypart,
|
||||
input.SlotKind,
|
||||
input.Weekday
|
||||
);
|
||||
|
||||
target.UpdateTiming(
|
||||
input.Weekday,
|
||||
input.TargetStart,
|
||||
input.TargetDurationMinutes,
|
||||
input.Daypart,
|
||||
input.IsAnchor,
|
||||
input.MaxDriftMinutes,
|
||||
input.SnapToMinutes
|
||||
);
|
||||
target.UpdateContent(
|
||||
input.Title,
|
||||
input.SlotKind,
|
||||
input.GroupId,
|
||||
input.Strategy?.ToJson(),
|
||||
input.RepeatSource?.ToJson(),
|
||||
input.BlockMode,
|
||||
input.BlockValue,
|
||||
input.OverflowPolicy,
|
||||
input.JunctionBetweenId,
|
||||
input.JunctionAfterId
|
||||
);
|
||||
|
||||
return Result.Success();
|
||||
}
|
||||
|
||||
/// <summary>Загружает шаблон целиком по слою — правка слота меняет ревизию всего шаблона.</summary>
|
||||
public Task<ScheduleTemplate?> LoadTemplateByLayerAsync(
|
||||
Guid layerId,
|
||||
CancellationToken cancellationToken
|
||||
) =>
|
||||
dbContext
|
||||
.ScheduleTemplates.Include(t => t.Layers)
|
||||
.ThenInclude(l => l.Slots)
|
||||
.FirstOrDefaultAsync(t => t.Layers.Any(l => l.Id == layerId), cancellationToken);
|
||||
|
||||
/// <summary>Загружает шаблон по слоту.</summary>
|
||||
public Task<ScheduleTemplate?> LoadTemplateBySlotAsync(
|
||||
Guid slotId,
|
||||
CancellationToken cancellationToken
|
||||
) =>
|
||||
dbContext
|
||||
.ScheduleTemplates.Include(t => t.Layers)
|
||||
.ThenInclude(l => l.Slots)
|
||||
.FirstOrDefaultAsync(
|
||||
t => t.Layers.Any(l => l.Slots.Any(s => s.Id == slotId)),
|
||||
cancellationToken
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user