using Marco.Pms.Model.MongoDBModels.Expenses; using Marco.Pms.Model.Utilities; using Microsoft.Extensions.Configuration; using MongoDB.Driver; namespace Marco.Pms.Helpers.CacheHelper { public class ExpenseCache { private readonly IMongoCollection _collection; public ExpenseCache(IConfiguration configuration) { var connectionString = configuration["MongoDB:ConnectionString"]; var mongoUrl = new MongoUrl(connectionString); var client = new MongoClient(mongoUrl); // Your MongoDB connection string var mongoDB = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name _collection = mongoDB.GetCollection("Expenses"); } public async Task AddExpenseToCacheAsync(ExpenseDetailsMongoDB expense) { await _collection.InsertOneAsync(expense); await InitializeCollectionAsync(); } public async Task AddExpensesListToCacheAsync(List expenses) { // 1. Add a guard clause to avoid an unnecessary database call for an empty list. if (expenses == null || !expenses.Any()) { return; } // 2. Perform the insert operation. This is the only responsibility of this method. await _collection.InsertManyAsync(expenses); await InitializeCollectionAsync(); } public async Task<(int totalPages, long totalCount, List expenseList)> GetExpenseListFromCacheAsync(Guid tenantId, Guid loggedInEmployeeId, bool viewAll, bool viewSelf, int pageNumber, int pageSize, ExpensesFilter? expenseFilter) { var filterBuilder = Builders.Filter; var filter = filterBuilder.Empty; // Permission-based filter if (!viewAll && viewSelf) { filter &= filterBuilder.Eq(e => e.CreatedById, loggedInEmployeeId.ToString()); } // Apply filters if (expenseFilter != null) { if (expenseFilter.StartDate.HasValue && expenseFilter.EndDate.HasValue) { filter &= filterBuilder.Gte(e => e.CreatedAt, expenseFilter.StartDate.Value.Date) & filterBuilder.Lte(e => e.CreatedAt, expenseFilter.EndDate.Value.Date.AddDays(1).AddTicks(-1)); } if (expenseFilter.ProjectIds?.Any() == true) { filter &= filterBuilder.In(e => e.ProjectId, expenseFilter.ProjectIds.Select(p => p.ToString()).ToList()); } if (expenseFilter.StatusIds?.Any() == true) { filter &= filterBuilder.In(e => e.StatusId, expenseFilter.StatusIds.Select(p => p.ToString()).ToList()); } if (expenseFilter.PaidById?.Any() == true) { filter &= filterBuilder.In(e => e.PaidById, expenseFilter.PaidById.Select(p => p.ToString()).ToList()); } if (expenseFilter.CreatedByIds?.Any() == true && viewAll) { filter &= filterBuilder.In(e => e.CreatedById, expenseFilter.CreatedByIds.Select(p => p.ToString()).ToList()); } } // Total count var totalCount = await _collection.CountDocumentsAsync(filter); var totalPages = (int)Math.Ceiling((double)totalCount / pageSize); // Fetch paginated data var expenses = await _collection .Find(filter) .Skip((pageNumber - 1) * pageSize) .Limit(pageSize) .SortByDescending(e => e.CreatedAt) .ToListAsync(); return (totalPages, totalCount, expenses); } public async Task GetExpenseDetailsByIdAsync(Guid id, Guid tenantId) { var filter = Builders.Filter.And( Builders.Filter.Eq(e => e.Id, id.ToString()), Builders.Filter.Eq(e => e.TenantId, tenantId.ToString()) ); var expense = await _collection.Find(filter).FirstOrDefaultAsync(); return expense; } public async Task DeleteExpenseFromCacheAsync(Guid id, Guid tenantId) { var filter = Builders.Filter.And( Builders.Filter.Eq(e => e.Id, id.ToString()), Builders.Filter.Eq(e => e.TenantId, tenantId.ToString()) ); var result = await _collection.DeleteOneAsync(filter); return result.DeletedCount > 0; } private async Task InitializeCollectionAsync() { var indexKeys = Builders.IndexKeys.Ascending(x => x.ExpireAt); var indexOptions = new CreateIndexOptions { ExpireAfter = TimeSpan.Zero // required for fixed expiration time }; var indexModel = new CreateIndexModel(indexKeys, indexOptions); await _collection.Indexes.CreateOneAsync(indexModel); } } }