Add bulk poster filling endpoint and enhance show deletion options
ci / build-backend (push) Successful in 2m2s
ci / build-frontend (push) Successful in 57s
ci / tests (push) Failing after 2m27s
ci / sonar (push) Skipped

Introduced a new endpoint for bulk filling collection posters, allowing for automatic assignment of posters to collections without existing images. Updated the DeleteShowCommand to include an option for cutting shows from future airings, enhancing the deletion process. Refactored related components and API calls to support these features, ensuring a seamless user experience. Additionally, updated localization strings to reflect the new functionalities and adjusted tests to verify correct behavior.
This commit is contained in:
Leonid Pershin
2026-07-28 12:07:00 +03:00
parent 9db54a4625
commit 4a500583e7
22 changed files with 581 additions and 33 deletions
@@ -114,6 +114,66 @@ public sealed class TransactionIntegrationTests(PostgresFixture fixture)
.DeleteAssetArtifactsAsync(asset.Id, ".mkv", Arg.Any<CancellationToken>());
}
/// <summary>
/// Шоу, стоящее в будущем эфире, удаляется с флагом «вырезать из эфира»: пересборка канала
/// спасает не всегда — идущую запись она не трогает, а выключенный канал вещать не начнёт.
/// </summary>
[SkippableFact]
public async Task DeleteShow_WithSchedule_CutsFutureEntries()
{
var channel = Channel.Create("Канал", "kanal", DateTimeOffset.UnixEpoch);
var show = Show.Create("Шоу", ShowKind.Single);
var asset = MediaAsset.Register("live.mkv", ".mkv", MediaSource.Upload);
show.AddEpisode(asset.Id);
// Запись идёт прямо сейчас: пересборка её не удаляет, а значит и шоу не освобождает.
var running = ScheduleEntry.Program(
channel.Id,
asset.Id,
DateTimeOffset.UtcNow.AddMinutes(-5),
DateTimeOffset.UtcNow.AddMinutes(15),
show.Id,
0
);
await using (var seed = fixture.CreateContext())
{
seed.Channels.Add(channel);
seed.Shows.Add(show);
seed.MediaAssets.Add(asset);
seed.ScheduleEntries.Add(running);
await seed.SaveChangesAsync(CancellationToken.None);
}
await using (var db = fixture.CreateContext())
{
var result = await new DeleteShowCommandHandler(
db,
new GroupMembershipCleaner(
db,
new GroupStatsService(
db,
new GroupElementResolver(db),
new DynamicGroupResolver(
new GroupFilterMatcher(db),
new GroupElementResolver(db)
)
)
),
new ShowMediaEraser(db, Substitute.For<IMediaStorage>())
).Handle(new DeleteShowCommand(show.Id, WithSchedule: true), CancellationToken.None);
Assert.True(result.IsSuccess);
await db.SaveChangesAsync(CancellationToken.None);
}
await using var verify = fixture.CreateContext();
Assert.False(await verify.Shows.AnyAsync(s => s.Id == show.Id));
Assert.False(await verify.ScheduleEntries.AnyAsync(e => e.ShowId == show.Id));
// Медиа не просили — оно осталось.
Assert.True(await verify.MediaAssets.AnyAsync(a => a.Id == asset.Id));
}
/// <summary>
/// Удаление шоу «вместе с медиа»: ассеты, записи расписания и файлы уходят одной операцией.
/// Проверяется на настоящем Postgres — <c>ExecuteDelete</c> и транзакции InMemory не умеет.