Adsing file to delete from S3 in mongoDB while update expenes
This commit is contained in:
parent
0095cd54f6
commit
4370d5a350
@ -102,6 +102,16 @@ namespace Marco.Pms.Helpers.CacheHelper
|
|||||||
|
|
||||||
return expense;
|
return expense;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DeleteExpenseFromCacheAsync(Guid id, Guid tenantId)
|
||||||
|
{
|
||||||
|
var filter = Builders<ExpenseDetailsMongoDB>.Filter.And(
|
||||||
|
Builders<ExpenseDetailsMongoDB>.Filter.Eq(e => e.Id, id.ToString()),
|
||||||
|
Builders<ExpenseDetailsMongoDB>.Filter.Eq(e => e.TenantId, tenantId.ToString())
|
||||||
|
);
|
||||||
|
var result = await _collection.DeleteOneAsync(filter);
|
||||||
|
return result.DeletedCount > 0;
|
||||||
|
}
|
||||||
private async Task InitializeCollectionAsync()
|
private async Task InitializeCollectionAsync()
|
||||||
{
|
{
|
||||||
var indexKeys = Builders<ExpenseDetailsMongoDB>.IndexKeys.Ascending(x => x.ExpireAt);
|
var indexKeys = Builders<ExpenseDetailsMongoDB>.IndexKeys.Ascending(x => x.ExpireAt);
|
||||||
|
@ -1,21 +1,28 @@
|
|||||||
using Marco.Pms.Model.MongoDBModels.Utility;
|
using Marco.Pms.Model.MongoDBModels.Utility;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using MongoDB.Bson;
|
using MongoDB.Bson;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
namespace Marco.Pms.Helpers
|
namespace Marco.Pms.Helpers.Utility
|
||||||
{
|
{
|
||||||
public class UpdateLogHelper
|
public class UtilityMongoDBHelper
|
||||||
{
|
{
|
||||||
private readonly IMongoDatabase _mongoDatabase;
|
private readonly IMongoDatabase _mongoDatabase;
|
||||||
public UpdateLogHelper(IConfiguration configuration)
|
private readonly IConfiguration _configuration;
|
||||||
|
private readonly ILogger<UtilityMongoDBHelper> _logger;
|
||||||
|
public UtilityMongoDBHelper(IConfiguration configuration, ILogger<UtilityMongoDBHelper> logger)
|
||||||
{
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_logger = logger;
|
||||||
var connectionString = configuration["MongoDB:ModificationConnectionString"];
|
var connectionString = configuration["MongoDB:ModificationConnectionString"];
|
||||||
var mongoUrl = new MongoUrl(connectionString);
|
var mongoUrl = new MongoUrl(connectionString);
|
||||||
var client = new MongoClient(mongoUrl); // Your MongoDB connection string
|
var client = new MongoClient(mongoUrl); // Your MongoDB connection string
|
||||||
_mongoDatabase = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name
|
_mongoDatabase = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region =================================================================== Update Log Helper Functions ===================================================================
|
||||||
public async Task PushToUpdateLogsAsync(UpdateLogsObject oldObject, string collectionName)
|
public async Task PushToUpdateLogsAsync(UpdateLogsObject oldObject, string collectionName)
|
||||||
{
|
{
|
||||||
var collection = _mongoDatabase.GetCollection<UpdateLogsObject>(collectionName);
|
var collection = _mongoDatabase.GetCollection<UpdateLogsObject>(collectionName);
|
||||||
@ -87,5 +94,35 @@ namespace Marco.Pms.Helpers
|
|||||||
return bson;
|
return bson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region =================================================================== S3 deletion Helper Functions ===================================================================
|
||||||
|
|
||||||
|
public async Task PushToS3DeletionAsync(List<S3DeletionObject> deletionObject)
|
||||||
|
{
|
||||||
|
var bucketName = _configuration["AWS:BucketName"];
|
||||||
|
if (bucketName != null)
|
||||||
|
{
|
||||||
|
deletionObject = deletionObject.Select(d => new S3DeletionObject
|
||||||
|
{
|
||||||
|
BucketName = bucketName,
|
||||||
|
Key = d.Key,
|
||||||
|
Deleted = false
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
_logger.LogInformation("Delection object for bucket {BucketName} added to mongoDB", bucketName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var collection = _mongoDatabase.GetCollection<S3DeletionObject>("S3Delection");
|
||||||
|
await collection.InsertManyAsync(deletionObject);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while saving delection object for S3 to MogoDB");
|
||||||
|
}
|
||||||
|
_logger.LogInformation("Delection Objects added to MongoDB Successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
15
Marco.Pms.Model/MongoDBModels/Utility/S3DeletionObject.cs
Normal file
15
Marco.Pms.Model/MongoDBModels/Utility/S3DeletionObject.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.MongoDBModels.Utility
|
||||||
|
{
|
||||||
|
public class S3DeletionObject
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public string BucketName { get; set; } = string.Empty;
|
||||||
|
public string Key { get; set; } = string.Empty;
|
||||||
|
public bool Deleted { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,12 @@
|
|||||||
{
|
{
|
||||||
public class FileUploadModel
|
public class FileUploadModel
|
||||||
{
|
{
|
||||||
|
public Guid? DocumentId { get; set; }
|
||||||
public string? FileName { get; set; } // Name of the file (e.g., "image1.png")
|
public string? FileName { get; set; } // Name of the file (e.g., "image1.png")
|
||||||
public string? Base64Data { get; set; } // Base64-encoded string of the file
|
public string? Base64Data { get; set; } // Base64-encoded string of the file
|
||||||
public string? ContentType { get; set; } // MIME type (e.g., "image/png", "application/pdf")
|
public string? ContentType { get; set; } // MIME type (e.g., "image/png", "application/pdf")
|
||||||
public long FileSize { get; set; } // File size in bytes
|
public long FileSize { get; set; } // File size in bytes
|
||||||
public string? Description { get; set; } // Optional: Description or purpose of the file
|
public string? Description { get; set; } // Optional: Description or purpose of the file
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1026,12 +1026,49 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
|
|
||||||
public async Task<ExpenseDetailsMongoDB?> GetExpenseDetailsById(Guid id, Guid tenantId)
|
public async Task<ExpenseDetailsMongoDB?> GetExpenseDetailsById(Guid id, Guid tenantId)
|
||||||
{
|
{
|
||||||
var response = await _expenseCache.GetExpenseDetailsByIdAsync(id, tenantId);
|
try
|
||||||
if (response == null || response.Id == string.Empty)
|
|
||||||
{
|
{
|
||||||
|
var response = await _expenseCache.GetExpenseDetailsByIdAsync(id, tenantId);
|
||||||
|
if (response != null && response.Id != string.Empty)
|
||||||
|
{
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while fetching expense details from cache");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return response;
|
|
||||||
|
public async Task ReplaceExpenseAsync(Expenses expense)
|
||||||
|
{
|
||||||
|
bool response = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = await _expenseCache.DeleteExpenseFromCacheAsync(expense.Id, expense.TenantId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while deleting expense from cache");
|
||||||
|
}
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
await AddExpenseByObjectAsync(expense);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public async Task DeleteExpenseAsync(Guid id, Guid tenantId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await _expenseCache.DeleteExpenseFromCacheAsync(id, tenantId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while deleting expense from cache");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Marco.Pms.DataAccess.Data;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using Marco.Pms.Helpers;
|
using Marco.Pms.Helpers;
|
||||||
using Marco.Pms.Helpers.CacheHelper;
|
using Marco.Pms.Helpers.CacheHelper;
|
||||||
|
using Marco.Pms.Helpers.Utility;
|
||||||
using Marco.Pms.Model.Authentication;
|
using Marco.Pms.Model.Authentication;
|
||||||
using Marco.Pms.Model.Entitlements;
|
using Marco.Pms.Model.Entitlements;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
@ -186,7 +187,7 @@ builder.Services.AddScoped<DirectoryHelper>();
|
|||||||
builder.Services.AddScoped<MasterHelper>();
|
builder.Services.AddScoped<MasterHelper>();
|
||||||
builder.Services.AddScoped<ReportHelper>();
|
builder.Services.AddScoped<ReportHelper>();
|
||||||
builder.Services.AddScoped<CacheUpdateHelper>();
|
builder.Services.AddScoped<CacheUpdateHelper>();
|
||||||
builder.Services.AddScoped<UpdateLogHelper>();
|
builder.Services.AddScoped<UtilityMongoDBHelper>();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Cache Services
|
#region Cache Services
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Marco.Pms.DataAccess.Data;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using Marco.Pms.Helpers;
|
using Marco.Pms.Helpers.Utility;
|
||||||
using Marco.Pms.Model.Dtos.Expenses;
|
using Marco.Pms.Model.Dtos.Expenses;
|
||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
using Marco.Pms.Model.Entitlements;
|
using Marco.Pms.Model.Entitlements;
|
||||||
@ -30,7 +30,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
private readonly ILoggingService _logger;
|
private readonly ILoggingService _logger;
|
||||||
private readonly S3UploadService _s3Service;
|
private readonly S3UploadService _s3Service;
|
||||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||||
private readonly UpdateLogHelper _updateLogHelper;
|
private readonly UtilityMongoDBHelper _updateLogHelper;
|
||||||
private readonly CacheUpdateHelper _cache;
|
private readonly CacheUpdateHelper _cache;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
private static readonly Guid Draft = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8");
|
private static readonly Guid Draft = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8");
|
||||||
@ -40,7 +40,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
IDbContextFactory<ApplicationDbContext> dbContextFactory,
|
IDbContextFactory<ApplicationDbContext> dbContextFactory,
|
||||||
ApplicationDbContext context,
|
ApplicationDbContext context,
|
||||||
IServiceScopeFactory serviceScopeFactory,
|
IServiceScopeFactory serviceScopeFactory,
|
||||||
UpdateLogHelper updateLogHelper,
|
UtilityMongoDBHelper updateLogHelper,
|
||||||
CacheUpdateHelper cache,
|
CacheUpdateHelper cache,
|
||||||
ILoggingService logger,
|
ILoggingService logger,
|
||||||
S3UploadService s3Service,
|
S3UploadService s3Service,
|
||||||
@ -690,6 +690,63 @@ namespace Marco.Pms.Services.Service
|
|||||||
_logger.LogError(ex, "Concurrency conflict while updating project {ProjectId} ", id);
|
_logger.LogError(ex, "Concurrency conflict while updating project {ProjectId} ", id);
|
||||||
return ApiResponse<object>.ErrorResponse("Conflict occurred.", "This project has been modified by someone else. Please refresh and try again.", 409);
|
return ApiResponse<object>.ErrorResponse("Conflict occurred.", "This project has been modified by someone else. Please refresh and try again.", 409);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model.BillAttachments?.Any() ?? false)
|
||||||
|
{
|
||||||
|
var newBillAttachments = model.BillAttachments.Where(ba => ba.DocumentId == null && ba.IsActive).ToList();
|
||||||
|
if (newBillAttachments.Any())
|
||||||
|
{
|
||||||
|
await ProcessAndUploadAttachmentsAsync(newBillAttachments, existingExpense, loggedInEmployee.Id, tenantId);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
var deleteBillAttachments = model.BillAttachments.Where(ba => ba.DocumentId != null && !ba.IsActive).ToList();
|
||||||
|
if (deleteBillAttachments.Any())
|
||||||
|
{
|
||||||
|
var documentIds = deleteBillAttachments.Select(d => d.DocumentId).ToList();
|
||||||
|
|
||||||
|
var attachmentTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
var attachments = await dbContext.BillAttachments.AsNoTracking().Where(ba => documentIds.Contains(ba.DocumentId)).ToListAsync();
|
||||||
|
|
||||||
|
dbContext.BillAttachments.RemoveRange(attachments);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
});
|
||||||
|
var documentsTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
var documents = await dbContext.Documents.AsNoTracking().Where(ba => documentIds.Contains(ba.Id)).ToListAsync();
|
||||||
|
|
||||||
|
if (documents.Any())
|
||||||
|
{
|
||||||
|
dbContext.Documents.RemoveRange(documents);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
List<S3DeletionObject> deletionObject = new List<S3DeletionObject>();
|
||||||
|
foreach (var document in documents)
|
||||||
|
{
|
||||||
|
deletionObject.Add(new S3DeletionObject
|
||||||
|
{
|
||||||
|
Key = document.S3Key
|
||||||
|
});
|
||||||
|
if (!string.IsNullOrWhiteSpace(document.ThumbS3Key) && document.ThumbS3Key != document.S3Key)
|
||||||
|
{
|
||||||
|
deletionObject.Add(new S3DeletionObject
|
||||||
|
{
|
||||||
|
Key = document.ThumbS3Key
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await _updateLogHelper.PushToS3DeletionAsync(deletionObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(attachmentTask, documentsTask);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Task to save the detailed audit log to a separate system (e.g., MongoDB).
|
// Task to save the detailed audit log to a separate system (e.g., MongoDB).
|
||||||
@ -718,9 +775,11 @@ namespace Marco.Pms.Services.Service
|
|||||||
});
|
});
|
||||||
}).Unwrap();
|
}).Unwrap();
|
||||||
|
|
||||||
await Task.WhenAll(mongoDBTask, getNextStatusesTask);
|
var cacheUpdateTask = _cache.ReplaceExpenseAsync(existingExpense);
|
||||||
|
|
||||||
var nextPossibleStatuses = await getNextStatusesTask;
|
await Task.WhenAll(mongoDBTask, getNextStatusesTask, cacheUpdateTask);
|
||||||
|
|
||||||
|
var nextPossibleStatuses = getNextStatusesTask.Result;
|
||||||
|
|
||||||
var response = _mapper.Map<ExpenseList>(existingExpense);
|
var response = _mapper.Map<ExpenseList>(existingExpense);
|
||||||
if (nextPossibleStatuses != null)
|
if (nextPossibleStatuses != null)
|
||||||
|
@ -42,7 +42,8 @@ namespace Marco.Pms.Services.Service
|
|||||||
if (allowedFilesType == null || !allowedFilesType.Contains(fileType))
|
if (allowedFilesType == null || !allowedFilesType.Contains(fileType))
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Unsupported file type. {FileType}", fileType);
|
_logger.LogWarning("Unsupported file type. {FileType}", fileType);
|
||||||
throw new InvalidOperationException("Unsupported file type.");
|
//throw new InvalidOperationException("Unsupported file type.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileBytes = Convert.FromBase64String(base64);
|
fileBytes = Convert.FromBase64String(base64);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user