diff --git a/src/Somnia.GuestLog/Components/Pages/StayExport/StayExportList.razor b/src/Somnia.GuestLog/Components/Pages/StayExport/StayExportList.razor index 617bace..840e5e7 100644 --- a/src/Somnia.GuestLog/Components/Pages/StayExport/StayExportList.razor +++ b/src/Somnia.GuestLog/Components/Pages/StayExport/StayExportList.razor @@ -154,24 +154,23 @@ private async Task BtnDeleteItem(StayExportFileDTO item) { - userMessage.ShowMessage("Not Implemented!", MessageKind.Normal); - @* bool? confirmDelete = await _confirmDeleteMsgBox.MsgBox.ShowAsync(); + bool? confirmDelete = await _confirmDeleteMsgBox.MsgBox.ShowAsync(); if (confirmDelete is null || confirmDelete.Value == false) { return; } - Result deleteResult = await stayExportEntityService.Delete(item); + Result deleteResult = await ExportService.DeleteExportedFileAsync(item); if (!deleteResult.IsSuccess) { - string errorMsg = $"Error deleting Stay {item.Id}"; + string errorMsg = $"Error deleting Export file {item.Id}"; userMessage.ShowResultWithMessage(deleteResult, errorMsg); return; } - userMessage.ShowMessage($"Stay {item.Id} deleted!", MessageKind.Success); - await LoadDataAsync(); *@ + userMessage.ShowMessage($"Export file {item.Id} deleted!", MessageKind.Success); + await LoadDataAsync(); } #endregion diff --git a/src/Somnia.GuestLog/Enums/Services/ResultCode.cs b/src/Somnia.GuestLog/Enums/Services/ResultCode.cs index 2eb51f2..50eec5c 100644 --- a/src/Somnia.GuestLog/Enums/Services/ResultCode.cs +++ b/src/Somnia.GuestLog/Enums/Services/ResultCode.cs @@ -7,6 +7,7 @@ public enum ResultCode UnknownError, FailedValidation, NotFound, + FileStorageError, //Specific Codes GuestInStay, diff --git a/src/Somnia.GuestLog/Resources/LanguageLocale.resx b/src/Somnia.GuestLog/Resources/LanguageLocale.resx index 92b2211..0b9252b 100644 --- a/src/Somnia.GuestLog/Resources/LanguageLocale.resx +++ b/src/Somnia.GuestLog/Resources/LanguageLocale.resx @@ -195,6 +195,7 @@ Unknown Error Failed entity validation Not found + File Storage Error Guest (ID: '{0}') is in a stay. Guest (ID: '{0}') is already in one stay during the period: {1} diff --git a/src/Somnia.GuestLog/Services/Entity/IStayExportFileEntityService.cs b/src/Somnia.GuestLog/Services/Entity/IStayExportFileEntityService.cs index 1f9ecac..ded83f7 100644 --- a/src/Somnia.GuestLog/Services/Entity/IStayExportFileEntityService.cs +++ b/src/Somnia.GuestLog/Services/Entity/IStayExportFileEntityService.cs @@ -7,6 +7,12 @@ public interface IStayExportFileEntityService public Task CreateStayExportAsync(StayExportFileDTO dto); public Task UpdateStayExportAsync(StayExportFileDTO dto); + /// + /// Delete StayExport entry from DB. + /// Exported File won't be deleted from Storage. + /// + public Task DeleteStayExportAsync(StayExportFileDTO dto); + public Task GetDtoByIdAsync(long id); //public Task> GetDtoListByFilterAsync(StayExportFileFilterDTO filter, int limit = 0); public Task> GetDtoListAsync(int limit = 0); diff --git a/src/Somnia.GuestLog/Services/Entity/StayExportFileEntityService.cs b/src/Somnia.GuestLog/Services/Entity/StayExportFileEntityService.cs index 99456a1..fe97fe2 100644 --- a/src/Somnia.GuestLog/Services/Entity/StayExportFileEntityService.cs +++ b/src/Somnia.GuestLog/Services/Entity/StayExportFileEntityService.cs @@ -1,5 +1,6 @@ using FluentValidation; using Microsoft.EntityFrameworkCore; +using Somnia.GuestLog.Enums.Services; using Somnia.GuestLog.Infrastructure; using Somnia.GuestLog.Models; using Somnia.GuestLog.Models.DTOs; @@ -59,6 +60,33 @@ public class StayExportFileEntityService( throw new NotImplementedException(); } + public async Task DeleteStayExportAsync(StayExportFileDTO dto) + { + try + { + using var dbContext = contextFactory.CreateDbContext(); + + int deletedCount = await dbContext.StayExportFiles + .Where(e => e.Id == dto.Id) + .ExecuteDeleteAsync(); + + if (deletedCount == 0) + { + logger.LogWarning("StayExportFileService - DeleteStayExportAsync: Error deleting StayExport. Entity not found with ID: '{ID}'", dto.Id); + return Result.Fail(ResultCode.NotFound); + } + + logger.LogInformation( + "StayExportFileService - DeleteStayExportAsync: StayExport deleted with Id: '{id}'.", dto.Id); + return Result.Ok(); + } + catch (Exception ex) + { + logger.LogError(ex, "StayExportFileService - DeleteStayExportAsync: Error creating GuestDocument"); + return Result.FailUnknownError(); + } + } + public async Task GetDtoByIdAsync(long id) { diff --git a/src/Somnia.GuestLog/Services/StayExport/StayExportService.cs b/src/Somnia.GuestLog/Services/StayExport/StayExportService.cs index f3247a6..bdf2894 100644 --- a/src/Somnia.GuestLog/Services/StayExport/StayExportService.cs +++ b/src/Somnia.GuestLog/Services/StayExport/StayExportService.cs @@ -160,13 +160,26 @@ public class StayExportService( return Result.Ok(); } - public Task DeleteExportedFileAsync(StayExportFileDTO item) + public async Task DeleteExportedFileAsync(StayExportFileDTO item) { - throw new NotImplementedException(); + //Try to delete existing file. + if (!string.IsNullOrEmpty(item.ExportedPath)) + { + bool fileDeletedFromStore = await DeleteExportFileFromStoreAsync(item); + if (!fileDeletedFromStore) + { + return Result.Fail(ResultCode.FileStorageError); + } + } - //TODO: - // - Delete file from "Store" if exists. - // - Delete entry from DB. + //Delete entry from DB. + Result deleteResult = await stayExportEntityService.DeleteStayExportAsync(item); + if (!deleteResult.IsSuccess) + { + return Result.Fail(deleteResult.ResultCode); + } + + return Result.Ok(); } @@ -194,6 +207,31 @@ public class StayExportService( throw new InvalidOperationException($"StayExportFile - Error getting stays using params: export type invalid: {exportParams.ExportType}"); } + private async Task DeleteExportFileFromStoreAsync(StayExportFileDTO item) + { + Debug.Assert(!string.IsNullOrEmpty(item.ExportedPath)); + + try + { + IStore store = GetExportStore(); + bool objectExist = await store.ObjectExists(item.ExportedPath); + if (!objectExist) + { + logger.LogWarning("StayExportService - File for item {id} not found in store! Skip delete!", item.Id); + return true; + } + + await store.DeleteObject(item.ExportedPath); + logger.LogInformation("StayExportService - File for item {id} deleted from path {path}", item.Id, item.ExportedPath); + return true; + } + catch (Exception ex) + { + logger.LogError(ex, "StayExportService - Error deleting export file of item {id}", item.Id); + return false; + } + } + private IStore GetExportStore() { string? storageConnString = config.ExportStorageConnectionString;