using Microsoft.Extensions.Options; using MongoDB.Driver; using UGQDataAccess.Repository.Models; using UGQDataAccess.Settings; using UGQDatabase.Models; public enum AccountGradeSortType { UpdatedAtAsc, UpdatedAtDesc, GradeAsc, GradeDesc, ReservedAtAsc, ReservedDesc, } public enum AccountGradeProcessType { All, Processing, Completed, } namespace UGQDataAccess.Repository { public class ReserveAccountGradeRepository : BaseRepository { private const string CollectionName = "ReserveAccountGrade"; public ReserveAccountGradeRepository(IMongoClient mongoClient, IOptions settings) : base(mongoClient, settings.Value.DatabaseName, CollectionName) { } public async Task get(string userGuid) { var builder = Builders.Filter; var filter = builder.Eq(x => x.IsCompleted, false); filter &= builder.Eq(x => x.UserGuid, userGuid); return await Collection.Find(filter).FirstOrDefaultAsync(); } public async Task> get(string userGuid, AccountGradeProcessType processType) { var builder = Builders.Filter; var filter = builder.Eq(x => x.UserGuid, userGuid); switch (processType) { case AccountGradeProcessType.Processing: filter &= builder.Eq(x => x.IsCompleted, false); break; case AccountGradeProcessType.Completed: filter &= builder.Eq(x => x.IsCompleted, true); break; case AccountGradeProcessType.All: default: break; } return await Collection.Find(filter).ToListAsync(); } public async Task getAllCount() { var builder = Builders.Filter; var filter = builder.Empty; var result = await Collection.Find(filter).CountDocumentsAsync(); return result; } public async Task reserveAccountGrade(string userGuid, UgqGradeType beforeGrade, UgqGradeType reserveGrade, DateTime reserveTime) { var entity = new ReserveAccountGradeEntity { UserGuid = userGuid, BeforeGradeType = beforeGrade, ReserveGradeType = reserveGrade, ReserveTime = reserveTime, UpdatedAt = DateTime.UtcNow, IsCompleted = false, }; await Collection.InsertOneAsync(entity); return entity; } public async Task modifyReserveAccountGrade(string reserveId, UgqGradeType reserveGrade, DateTime reserveTime) { var builder = Builders.Filter; var filter = builder.Eq(x => x.IsCompleted, false); filter &= builder.Eq(x => x.Id, reserveId); var update = Builders.Update .Set(x => x.ReserveGradeType, reserveGrade) .Set(x => x.ReserveTime, reserveTime) .Set(x => x.UpdatedAt, DateTime.UtcNow); var options = new FindOneAndUpdateOptions { ReturnDocument = ReturnDocument.After, }; return await Collection.FindOneAndUpdateAsync(filter, update, options); } public async Task> completeReserveAccountGrade() { var builder = Builders.Filter; var filter = builder.Eq(x => x.IsCompleted, false); filter &= builder.Lte(x => x.ReserveTime, DateTime.UtcNow); var update = Builders.Update .Set(x => x.IsCompleted, true) .Set(x => x.UpdatedAt, DateTime.UtcNow); var result = await Collection.Find(filter).ToListAsync(); await Collection.UpdateManyAsync(filter, update); return result; } public async Task deleteReserveAccountGrade(string reserveId) { var builder = Builders.Filter; var filter = builder.Eq(x => x.IsCompleted, false); filter &= builder.Eq(x => x.Id, reserveId); var result = await Collection.DeleteOneAsync(filter); if (result.DeletedCount == 0) return ServerErrorCode.UgqNullEntity; return ServerErrorCode.Success; } public async Task getAccounts(int pageNumber, int pageSize, AccountGradeSortType sortType, AccountGradeProcessType processType, string userGuid) { pageNumber = pageNumber < 1 ? 1 : pageNumber; var builder = Builders.Filter; var filter = Builders.Filter.Empty; switch (processType) { case AccountGradeProcessType.Processing: filter = builder.Eq(x => x.IsCompleted, false); break; case AccountGradeProcessType.Completed: filter = builder.Eq(x => x.IsCompleted, true); break; case AccountGradeProcessType.All: default: break; } if(userGuid != string.Empty) filter &= builder.Eq(x => x.UserGuid, userGuid); var sortBuilder = Builders.Sort; SortDefinition sort; switch (sortType) { case AccountGradeSortType.UpdatedAtAsc: sort = Builders.Sort.Ascending("UpdatedAt"); break; case AccountGradeSortType.UpdatedAtDesc: sort = Builders.Sort.Descending("UpdatedAt"); break; case AccountGradeSortType.GradeAsc: sort = Builders.Sort.Ascending("CurrentGradeType"); break; case AccountGradeSortType.GradeDesc: sort = Builders.Sort.Descending("CurrentGradeType"); break; case AccountGradeSortType.ReservedAtAsc: sort = Builders.Sort.Ascending("ReserveTime"); break; case AccountGradeSortType.ReservedDesc: sort = Builders.Sort.Descending("ReserveTime"); break; default: sort = Builders.Sort.Descending("UpdatedAt"); break; } var countFacet = AggregateFacet.Create("count", new EmptyPipelineDefinition() .Count() ); var pagingFacet = AggregateFacet.Create("paging", new EmptyPipelineDefinition() .Sort(sort) .Skip((pageNumber - 1) * pageSize) .Limit(pageSize) ); var pipeline = ReserveAccountGradeQuery.allReserveAccountGradePipeline( filter, ReserveAccountGradeQuery.ReserveAccountGradeItemResultProjection) .Facet(countFacet, pagingFacet); var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync(); var count = aggregation.First() .Facets.First(x => x.Name == "count") .Output() ?.FirstOrDefault() ?.Count; var paging = aggregation.First() .Facets.First(x => x.Name == "paging") .Output(); int totalPages = 0; if (count != null) totalPages = (int)Math.Ceiling((double)count / pageSize); var result = await (await Collection.AggregateAsync(pipeline)).ToListAsync(); return new AllReserveAccountGradeResult { PageNumber = pageNumber, PageSize = pageSize, TotalPages = totalPages, Items = paging.ToList(), }; } } }