diff --git a/src/ScadaLink.TemplateEngine/Services/TemplateFolderService.cs b/src/ScadaLink.TemplateEngine/Services/TemplateFolderService.cs index 5f23938..24899ad 100644 --- a/src/ScadaLink.TemplateEngine/Services/TemplateFolderService.cs +++ b/src/ScadaLink.TemplateEngine/Services/TemplateFolderService.cs @@ -122,4 +122,37 @@ public class TemplateFolderService return Result.Success(folder); } + + public async Task> DeleteFolderAsync( + int folderId, string user, + CancellationToken cancellationToken = default) + { + var folder = await _repository.GetFolderByIdAsync(folderId, cancellationToken); + if (folder == null) + return Result.Failure($"Folder with ID {folderId} not found."); + + var allFolders = await _repository.GetAllFoldersAsync(cancellationToken); + var allTemplates = await _repository.GetAllTemplatesAsync(cancellationToken); + + var childFolderCount = allFolders.Count(f => f.ParentFolderId == folderId); + var childTemplateCount = allTemplates.Count(t => t.FolderId == folderId); + + if (childFolderCount > 0 || childTemplateCount > 0) + { + var parts = new List(); + if (childTemplateCount > 0) + parts.Add($"{childTemplateCount} template{(childTemplateCount == 1 ? "" : "s")}"); + if (childFolderCount > 0) + parts.Add($"{childFolderCount} subfolder{(childFolderCount == 1 ? "" : "s")}"); + return Result.Failure( + $"Cannot delete folder '{folder.Name}': it contains {string.Join(" and ", parts)}. " + + "Move or delete contents first."); + } + + await _repository.DeleteFolderAsync(folderId, cancellationToken); + await _repository.SaveChangesAsync(cancellationToken); + await _auditService.LogAsync(user, "Delete", "TemplateFolder", folderId.ToString(), folder.Name, null, cancellationToken); + + return Result.Success(true); + } } diff --git a/tests/ScadaLink.TemplateEngine.Tests/Services/TemplateFolderServiceTests.cs b/tests/ScadaLink.TemplateEngine.Tests/Services/TemplateFolderServiceTests.cs index cf2f87a..2dece19 100644 --- a/tests/ScadaLink.TemplateEngine.Tests/Services/TemplateFolderServiceTests.cs +++ b/tests/ScadaLink.TemplateEngine.Tests/Services/TemplateFolderServiceTests.cs @@ -186,4 +186,54 @@ public class TemplateFolderServiceTests Assert.True(result.IsFailure); Assert.Contains("cycle", result.Error, StringComparison.OrdinalIgnoreCase); } + + [Fact] + public async Task DeleteFolder_Empty_ReturnsSuccess() + { + var f = new TemplateFolder("Empty") { Id = 1 }; + _repoMock.Setup(r => r.GetFolderByIdAsync(1, It.IsAny())).ReturnsAsync(f); + _repoMock.Setup(r => r.GetAllFoldersAsync(It.IsAny())) + .ReturnsAsync(new List { f }); + _repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny())) + .ReturnsAsync(new List