Implement template export/import endpoints and enhance grid generation logic
Added new endpoints for exporting and importing grid configurations in TemplateEndpoints, allowing for better management of template data. Enhanced the GenerateGridCommandHandler to support seasonal layers in grid generation, improving scheduling accuracy during holiday periods. Updated related classes and records to accommodate these changes, ensuring a cohesive integration of new features. Improved documentation for clarity and maintainability.
This commit is contained in:
@@ -340,6 +340,74 @@ public class BumperResolverTests
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Resolve_AnnouncesTonightsPrime()
|
||||
{
|
||||
var template = TemplateWith(Title("СЕГОДНЯ В {tonight.time} — {tonight.title}"));
|
||||
|
||||
var fixture = new TestDb();
|
||||
var channel = Channel.Create("Первый", "one", T0);
|
||||
// Канал в UTC: так время в анонсе читается без пересчёта в уме.
|
||||
channel.UpdateTimeSettings(null, 0, Channel.DefaultDayStartTime);
|
||||
var from = Show.Create("Симпсоны", ShowKind.Series);
|
||||
var to = Show.Create("Гриффины", ShowKind.Series);
|
||||
var feature = Show.Create("Терминатор", ShowKind.Single);
|
||||
|
||||
var grid = ScheduleTemplate.Create(channel.Id, "Сетка");
|
||||
var day = grid.Background!.AddSlot("Дневной блок", new TimeOnly(14, 0), 240);
|
||||
var prime = grid.Background!.AddSlot("Вечернее кино", new TimeOnly(20, 0), 120);
|
||||
prime.UpdateTiming(null, new TimeOnly(20, 0), 120, Daypart.Prime, false, 30, null);
|
||||
|
||||
await using (var seed = fixture.New())
|
||||
{
|
||||
seed.Channels.Add(channel);
|
||||
seed.BumperTemplates.Add(template);
|
||||
seed.Shows.AddRange(from, to, feature);
|
||||
seed.ScheduleTemplates.Add(grid);
|
||||
await seed.SaveChangesAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
var items = Lente(template.Id, from.Id, to.Id, day.Id);
|
||||
// Вечером тех же вещательных суток стоит фильм в прайме — его и должен назвать анонс.
|
||||
items.Add(
|
||||
new PlannedItem(
|
||||
Guid.NewGuid(),
|
||||
T0.AddHours(2),
|
||||
T0.AddHours(4),
|
||||
feature.Id,
|
||||
0,
|
||||
prime.Id,
|
||||
PlannedItemKind.Program
|
||||
)
|
||||
);
|
||||
|
||||
await using var db = fixture.New();
|
||||
var assets = await NewResolver(db).ResolveAsync(channel, items, CancellationToken.None);
|
||||
await db.SaveChangesAsync(CancellationToken.None);
|
||||
|
||||
await using var verify = fixture.New();
|
||||
var cache = await verify.BumperAssets.SingleAsync(b => b.MediaAssetId == assets[1]);
|
||||
var line = Assert.Single(BumperRenderedText.FromJson(cache.RenderedLinesJson));
|
||||
Assert.Equal("СЕГОДНЯ В 20:00 — Терминатор", line.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Resolve_SkipsAnnouncementThatAlreadyStarted()
|
||||
{
|
||||
var template = TemplateWith(Title("СЕГОДНЯ В {tonight.time} — {tonight.title}"));
|
||||
var (fixture, channel, from, to) = await SeedAsync(template);
|
||||
|
||||
// Прайма впереди нет — анонсировать нечего, и строка обязана схлопнуться, а не соврать.
|
||||
await using var db = fixture.New();
|
||||
var assets = await NewResolver(db)
|
||||
.ResolveAsync(channel, Lente(template.Id, from.Id, to.Id), CancellationToken.None);
|
||||
await db.SaveChangesAsync(CancellationToken.None);
|
||||
|
||||
await using var verify = fixture.New();
|
||||
var cache = await verify.BumperAssets.SingleAsync(b => b.MediaAssetId == assets[1]);
|
||||
Assert.Empty(BumperRenderedText.FromJson(cache.RenderedLinesJson));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Resolve_IgnoresReservationsWithoutTemplate()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user