diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs index cc436d7..eebf05d 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs @@ -15,13 +15,24 @@ public class AuctionBidDbTable : MgDbTableBase { } - public IQueryable GetLastAuctionBidByProductToAuctionId(int productToAuctionId) - => GetByProductToAuctionId(productToAuctionId).OrderByDescending(x => x.Id); + public IOrderedQueryable GetAllLastBidByAuctionId(int auctionId) + { + return GetAllByAuctionId(auctionId) + .OrderByDescending(x => x.Id) + .GroupBy(x => x.AuctionId, (_, bids) => bids.FirstOrDefault()) + .OrderByDescending(percentGroup => percentGroup.Id); + } + + public IOrderedQueryable GetLastAuctionBidByProductToAuctionId(int productToAuctionId) + => GetAllByProductToAuctionId(productToAuctionId).OrderByDescending(x => x.Id); public Task GetBidsCountByProductToAuctionIdAsync(int productToAuctionId) => Table.CountAsync(x => x.ProductAuctionMappingId == productToAuctionId); - - public IQueryable GetByProductToAuctionId(int productToAuctionId) + + public IQueryable GetAllByAuctionId(int auctionId) + => Table.Where(x => x.AuctionId == auctionId); + + public IQueryable GetAllByProductToAuctionId(int productToAuctionId) => Table.Where(x => x.ProductAuctionMappingId == productToAuctionId); public Task HasBidByProductToAuctionIdAsync(int productToAuctionId) diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs index 80cdc8b..cb0254b 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs @@ -44,6 +44,10 @@ public class AuctionDbContext : MgDbContextBase, IAuctionDbSet, // AuctionBids2 = _auctionBidRepository; //} + public Task> GetAllLastBidByAuctionIdAsync(int auctionId) => AuctionBids.GetAllLastBidByAuctionId(auctionId).ToListAsync(); + public Task> GetAllLastBidDictionaryByAuctionIdAsync(int auctionId) + => AuctionBids.GetAllLastBidByAuctionId(auctionId).ToDictionaryAsync(x => x.ProductAuctionMappingId); + public async Task> GetProductToAuctionsByProductIdAsync(int productId) { return [..await ProductToAuctions.GetByProductId(productId).ToListAsync()]; diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/AuctionBid.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/AuctionBid.cs index 9695fd8..df8d419 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/AuctionBid.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/AuctionBid.cs @@ -8,6 +8,7 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Domains.Entities { public partial class AuctionBid : MgEntityBase, IAuctionBid { + public int AuctionId { get; set; } public int ProductAuctionMappingId { get; set; } public int CustomerId { get; set; } diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/Interfaces/IAuctionBid.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/Interfaces/IAuctionBid.cs index cfc544e..10f2a50 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/Interfaces/IAuctionBid.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/Entities/Interfaces/IAuctionBid.cs @@ -5,5 +5,5 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Domains.Entities.Interfaces; public interface IAuctionBid : IAuctionBidDtoBase, ITimeStampInfo//, ISoftRemoveEntityInt { - + public int AuctionId { get; set; } } \ No newline at end of file diff --git a/Nop.Plugin.Misc.AuctionPlugin/Hubs/AuctionHub.cs b/Nop.Plugin.Misc.AuctionPlugin/Hubs/AuctionHub.cs index 7215542..c9e829c 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Hubs/AuctionHub.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Hubs/AuctionHub.cs @@ -19,7 +19,7 @@ using Microsoft.IdentityModel.Tokens; namespace Nop.Plugin.Misc.AuctionPlugin.Hubs { - public class AuctionHub(SessionService sessionService, ILockService lockService, ILogger logger, IProductService productService, AuctionService auctionService, IWorkContext workContext, ICustomerService customerService, ICategoryService categoryService) + public class AuctionHub(SessionService sessionService, ILockService lockService, ILogger logger, IProductService productService, AuctionService auctionService, IWorkContext workContext, ICustomerService customerService) : Hub { public override async Task OnConnectedAsync() @@ -182,7 +182,7 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs var revertLastBid = await auctionService.RevertAuctionBidByProductToAuctionIdAsync(productToAuction.Id); - if (revertLastBid == null) await ResetProductToAuction(productToAuction); + if (revertLastBid == null) await auctionService.ResetProductToAuction(productToAuction); else { productToAuction.BidsCount = await auctionService.GetBidsCountByProductToAuctionIdAsync(productToAuction.Id); @@ -288,7 +288,7 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs //var responseType = ResponseType.ToAllClients; await logger.InformationAsync($"AuctionHub.HandleProductToAuctionStatusChangedRequest(); ProductToAuctionMappingId: {auctionProductStatusRequest.ProductToAuctionId}; Status: {auctionProductStatusRequest.AuctionStatus}({(int)auctionProductStatusRequest.AuctionStatus})", null, customer); - var (auction, productToAuction, responseType) = await GetAndUpdateProductToAuctionStatusIfValidAsync(auctionProductStatusRequest.ProductToAuctionId, auctionProductStatusRequest.AuctionStatus, customer); + var (auction, productToAuction, responseType) = await auctionService.GetAndUpdateProductToAuctionStatusIfValidAsync(auctionProductStatusRequest.ProductToAuctionId, auctionProductStatusRequest.AuctionStatus, customer); if (auction == null || productToAuction == null || responseType == ResponseType.None) return ResponseType.None; await SendStatusChangedNotificationAsync(customer, statusChangedMessageWrapper, productToAuction, responseType); @@ -307,85 +307,85 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs return ResponseType.Error; } - private async Task UpdateProductToAuctionStatusIfValidAsync(AuctionStatus newProductToAuctionStatus, Auction auction, ProductToAuctionMapping productToAuction, Customer customer) - { - if (!IsValidRequestAuctionStatus(newProductToAuctionStatus, productToAuction.AuctionStatus)) - { - logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); RequestAuctionStatusIsValid() == false; newStatus: {newProductToAuctionStatus}; oldStatus: {productToAuction.AuctionStatus}", null, customer); + //private async Task UpdateProductToAuctionStatusIfValidAsync(AuctionStatus newProductToAuctionStatus, Auction auction, ProductToAuctionMapping productToAuction, Customer customer) + //{ + // if (!IsValidRequestAuctionStatus(newProductToAuctionStatus, productToAuction.AuctionStatus)) + // { + // logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); RequestAuctionStatusIsValid() == false; newStatus: {newProductToAuctionStatus}; oldStatus: {productToAuction.AuctionStatus}", null, customer); - return ResponseType.ToCaller; - } + // return ResponseType.ToCaller; + // } - if (newProductToAuctionStatus == AuctionStatus.None) await ResetProductToAuction(productToAuction, auction.CategoryId); - else - { - switch (newProductToAuctionStatus) - { - case AuctionStatus.Active: - productToAuction.AuctionStatus = AuctionStatus.Active; - await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, auction.CategoryId, true); - break; + // if (newProductToAuctionStatus == AuctionStatus.None) await ResetProductToAuction(productToAuction, auction.CategoryId); + // else + // { + // switch (newProductToAuctionStatus) + // { + // case AuctionStatus.Active: + // productToAuction.AuctionStatus = AuctionStatus.Active; + // await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, auction.CategoryId, true); + // break; - case AuctionStatus.FirstWarning: - case AuctionStatus.SecondWarning: - productToAuction.AuctionStatus = newProductToAuctionStatus; - break; + // case AuctionStatus.FirstWarning: + // case AuctionStatus.SecondWarning: + // productToAuction.AuctionStatus = newProductToAuctionStatus; + // break; - case AuctionStatus.Sold: - var lastAuctionBid = await auctionService.GetLastAuctionBidByProductToAuctionIdAsync(productToAuction.Id); - if (lastAuctionBid == null) productToAuction.AuctionStatus = AuctionStatus.NotSold; - else - { - productToAuction.AuctionStatus = AuctionStatus.Sold; - productToAuction.CurrentPrice = lastAuctionBid.BidPrice; - productToAuction.WinnerCustomerId = lastAuctionBid.CustomerId; + // case AuctionStatus.Sold: + // var lastAuctionBid = await auctionService.GetLastAuctionBidByProductToAuctionIdAsync(productToAuction.Id); + // if (lastAuctionBid == null) productToAuction.AuctionStatus = AuctionStatus.NotSold; + // else + // { + // productToAuction.AuctionStatus = AuctionStatus.Sold; + // productToAuction.CurrentPrice = lastAuctionBid.BidPrice; + // productToAuction.WinnerCustomerId = lastAuctionBid.CustomerId; - var placeOrderResult = await auctionService.CreateOrderForWinnerAsync(productToAuction); - if (placeOrderResult == null || placeOrderResult.Id == 0) - { - logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); (placeOrderResult == null || placeOrderResult.Id == 0)", null, customer); - //return; //TODO: EGYELŐRE HAGYJUK LEZÁRNI AKKOR IS, HA NEM SIKERÜLT AZ ORDERPLACE()! - J. - } - } + // var placeOrderResult = await auctionService.CreateOrderForWinnerAsync(productToAuction); + // if (placeOrderResult == null || placeOrderResult.Id == 0) + // { + // logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); (placeOrderResult == null || placeOrderResult.Id == 0)", null, customer); + // //return; //TODO: EGYELŐRE HAGYJUK LEZÁRNI AKKOR IS, HA NEM SIKERÜLT AZ ORDERPLACE()! - J. + // } + // } - await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, auction.CategoryId, false); - break; + // await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, auction.CategoryId, false); + // break; - case AuctionStatus.Pause: - productToAuction.AuctionStatus = AuctionStatus.Pause; - break; + // case AuctionStatus.Pause: + // productToAuction.AuctionStatus = AuctionStatus.Pause; + // break; - default: - logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); AuctionStatus not found; (newStatus == {newProductToAuctionStatus})", null, customer); + // default: + // logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); AuctionStatus not found; (newStatus == {newProductToAuctionStatus})", null, customer); - return ResponseType.ToCaller; - } + // return ResponseType.ToCaller; + // } - await auctionService.UpdateProductToAuctionMappingAsync(productToAuction); - } + // await auctionService.UpdateProductToAuctionMappingAsync(productToAuction); + // } - return ResponseType.ToAllClients; - } + // return ResponseType.ToAllClients; + //} - private async Task<(Auction auction, ProductToAuctionMapping productToAuction, ResponseType responseType)> GetAndUpdateProductToAuctionStatusIfValidAsync(int productToAuctionId, AuctionStatus newProductToAuctionStatus, Customer customer) - { - var productToAuction = await auctionService.GetProductToAuctionMappingByIdAsync(productToAuctionId); - if (productToAuction == null) - { - logger.Error($"AuctionHub.GetAndUpdateProductToAuctionStatusIfValidAsync(); (productToAuction == null)", null, customer); - return (null, null, ResponseType.None); - } + //private async Task<(Auction auction, ProductToAuctionMapping productToAuction, ResponseType responseType)> GetAndUpdateProductToAuctionStatusIfValidAsync(int productToAuctionId, AuctionStatus newProductToAuctionStatus, Customer customer) + //{ + // var productToAuction = await auctionService.GetProductToAuctionMappingByIdAsync(productToAuctionId); + // if (productToAuction == null) + // { + // logger.Error($"AuctionHub.GetAndUpdateProductToAuctionStatusIfValidAsync(); (productToAuction == null)", null, customer); + // return (null, null, ResponseType.None); + // } - var auction = await auctionService.GetAuctionByIdAsync(productToAuction.AuctionId); - if (auction == null || auction.Closed) - { - logger.Error($"AuctionHub.GetAndUpdateProductToAuctionStatusIfValidAsync(); (auction == null || auction.Closed); Closed: {auction?.Closed}", null, customer); - return (null, null, ResponseType.None); - } + // var auction = await auctionService.GetAuctionByIdAsync(productToAuction.AuctionId); + // if (auction == null || auction.Closed) + // { + // logger.Error($"AuctionHub.GetAndUpdateProductToAuctionStatusIfValidAsync(); (auction == null || auction.Closed); Closed: {auction?.Closed}", null, customer); + // return (null, null, ResponseType.None); + // } - var responseType = await UpdateProductToAuctionStatusIfValidAsync(newProductToAuctionStatus, auction, productToAuction, customer); - return (auction, productToAuction, responseType); - } + // var responseType = await UpdateProductToAuctionStatusIfValidAsync(newProductToAuctionStatus, auction, productToAuction, customer); + // return (auction, productToAuction, responseType); + //} private async Task SendStatusChangedNotificationAsync(Customer customer, MessageWrapper statusChangedMessageWrapper, ProductToAuctionMapping productToAuction, ResponseType responseType) { @@ -506,35 +506,35 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs }.ToJson(); } - private async Task ResetProductToAuction(ProductToAuctionMapping productToAuction, int? categoryId = null) - { - productToAuction.AuctionStatus = AuctionStatus.None; - await auctionService.ResetProductToAuctionAsync(productToAuction, productToAuction.StartingPrice); + //private async Task ResetProductToAuction(ProductToAuctionMapping productToAuction, int? categoryId = null) + //{ + // productToAuction.AuctionStatus = AuctionStatus.None; + // await auctionService.ResetProductToAuctionAsync(productToAuction, productToAuction.StartingPrice); - categoryId ??= (await auctionService.GetAuctionByIdAsync(productToAuction.AuctionId))?.CategoryId; - await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, categoryId, false); - } + // categoryId ??= (await auctionService.GetAuctionByIdAsync(productToAuction.AuctionId))?.CategoryId; + // await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, categoryId, false); + //} - private async Task UpdateProductCategoryIsFeaturedAsync(int productId, int? categoryId, bool isFeatured) - { - //Leszarjuk ha elszáll, az aukció menjen tovább... - J. - try - { - if (categoryId.GetValueOrDefault(0) == 0) return; + //private async Task UpdateProductCategoryIsFeaturedAsync(int productId, int? categoryId, bool isFeatured) + //{ + // //Leszarjuk ha elszáll, az aukció menjen tovább... - J. + // try + // { + // if (categoryId.GetValueOrDefault(0) == 0) return; - var productCategory = (await categoryService.GetProductCategoriesByProductIdAsync(productId)).FirstOrDefault(x => x.CategoryId == categoryId); - if (productCategory == null) return; + // var productCategory = (await categoryService.GetProductCategoriesByProductIdAsync(productId)).FirstOrDefault(x => x.CategoryId == categoryId); + // if (productCategory == null) return; - if (productCategory.IsFeaturedProduct == isFeatured) return; + // if (productCategory.IsFeaturedProduct == isFeatured) return; - productCategory.IsFeaturedProduct = isFeatured; - await categoryService.UpdateProductCategoryAsync(productCategory); - } - catch (Exception ex) - { - logger.Error($"AuctionHub.UpdateProductCategoryIsFeaturedAsync(); categoryId: {categoryId}; productId: {productId}; isFeatured: {isFeatured}", ex); - } - } + // productCategory.IsFeaturedProduct = isFeatured; + // await categoryService.UpdateProductCategoryAsync(productCategory); + // } + // catch (Exception ex) + // { + // logger.Error($"AuctionHub.UpdateProductCategoryIsFeaturedAsync(); categoryId: {categoryId}; productId: {productId}; isFeatured: {isFeatured}", ex); + // } + //} public async Task SendAuctionBidMessageAsync(MessageWrapper messageWrapper, ProductToAuctionMapping productToAuction, Product product, int customerId, ResponseType responseType) { @@ -559,11 +559,12 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs if (messageWrapper.HideToaster) await Clients.All.send(messageWrapperJson); else { + //messageWrapperJObject["senderId" /*nameof(MessageWrapper.SenderId)*/] = "-1"; await Clients.Others.send(messageWrapperJson); - + var messageWrapperJObject = JObject.Parse(messageWrapperJson); messageWrapperJObject["hideToaster" /*nameof(MessageWrapper.HideToaster)*/] = "true"; - + await Clients.Caller.send(messageWrapperJObject.ToString(Formatting.None)); } @@ -584,26 +585,26 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs // else await Clients.All.send(messageWrapper.ToJson()); //} - private static bool IsValidRequestAuctionStatus(AuctionStatus newStatus, AuctionStatus oldStatus) - { - switch (oldStatus) - { - case AuctionStatus.None: - return newStatus is AuctionStatus.Active or AuctionStatus.Pause; - case AuctionStatus.Active: - return newStatus is AuctionStatus.FirstWarning or AuctionStatus.Pause; - case AuctionStatus.FirstWarning: - return newStatus is AuctionStatus.SecondWarning or AuctionStatus.Pause; - case AuctionStatus.SecondWarning: - return newStatus is AuctionStatus.Sold or AuctionStatus.Pause; - case AuctionStatus.Pause: - return newStatus is AuctionStatus.None or AuctionStatus.Active; - case AuctionStatus.Sold: - case AuctionStatus.NotSold: - default: - return false; - } - } + //private static bool IsValidRequestAuctionStatus(AuctionStatus newStatus, AuctionStatus oldStatus) + //{ + // switch (oldStatus) + // { + // case AuctionStatus.None: + // return newStatus is AuctionStatus.Active or AuctionStatus.Pause; + // case AuctionStatus.Active: + // return newStatus is AuctionStatus.FirstWarning or AuctionStatus.Pause; + // case AuctionStatus.FirstWarning: + // return newStatus is AuctionStatus.SecondWarning or AuctionStatus.Pause; + // case AuctionStatus.SecondWarning: + // return newStatus is AuctionStatus.Sold or AuctionStatus.Pause; + // case AuctionStatus.Pause: + // return newStatus is AuctionStatus.None or AuctionStatus.Active; + // case AuctionStatus.Sold: + // case AuctionStatus.NotSold: + // default: + // return false; + // } + //} private bool TryGetCurrentSessionItem(out SessionItem sessionItem) { diff --git a/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionBackgroundService.cs b/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionBackgroundService.cs index 420db33..e9475a4 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionBackgroundService.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionBackgroundService.cs @@ -70,10 +70,18 @@ public class AuctionBackgroundService : MgBackgroundServiceBase var auctionDto = new AuctionDto(auction); var productToAuctions = (await _auctionService.GetProductToAuctionsByAuctionIdAsync(auction.Id, false)).Where(x => x.AuctionStatus == AuctionStatus.None).ToList(); + if (productToAuctions.Count == 0) continue; + + var allLastBidbyPtaId = await _auctionService.GetAllLastBidDictionaryByAuctionIdAsync(auction.Id); + foreach (var productToAuction in productToAuctions) { - productToAuction.AuctionStatus = AuctionStatus.Active; - auctionDto.ProductToAuctionDtos.Add(new ProductToAuctionDto(productToAuction)); + allLastBidbyPtaId.TryGetValue(productToAuction.Id, out var lastBid); + + var responseType = await _auctionService.UpdateProductToAuctionStatusIfValidAsync(AuctionStatus.Active, auction, productToAuction, _auctionSystemCustomer, false); + + if (responseType != ResponseType.None) + auctionDto.ProductToAuctionDtos.Add(new ProductToAuctionDto(productToAuction)); } await _auctionService.UpdateProductToAuctionMappingAsync(productToAuctions); diff --git a/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs b/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs index 06f8c56..f142270 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs @@ -22,6 +22,7 @@ using Nop.Services.Common; using Nop.Services.Customers; using Nop.Services.Shipping; using NUglify.Helpers; +using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities.Interfaces; namespace Nop.Plugin.Misc.AuctionPlugin.Services; @@ -39,8 +40,144 @@ public class AuctionService( IAddressService addressService, ICustomerService customerService, IOrderService orderService, - ILogger logger) : IAuctionService + ILogger logger, + ICategoryService categoryService) : IAuctionService { + #region AuctionHub + + public async Task UpdateProductToAuctionStatusIfValidAsync(AuctionStatus newProductToAuctionStatus, Auction auction, ProductToAuctionMapping productToAuction, Customer customer, bool updateInDatabase = true) + { + if (!IsValidRequestAuctionStatus(newProductToAuctionStatus, productToAuction.AuctionStatus)) + { + logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); RequestAuctionStatusIsValid() == false; newStatus: {newProductToAuctionStatus}; oldStatus: {productToAuction.AuctionStatus}", null, customer); + + return ResponseType.ToCaller; + } + + if (newProductToAuctionStatus == AuctionStatus.None) await ResetProductToAuction(productToAuction, auction.CategoryId); + else + { + switch (newProductToAuctionStatus) + { + case AuctionStatus.Active: + productToAuction.AuctionStatus = AuctionStatus.Active; + await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, auction.CategoryId, true); + break; + + case AuctionStatus.FirstWarning: + case AuctionStatus.SecondWarning: + productToAuction.AuctionStatus = newProductToAuctionStatus; + break; + + case AuctionStatus.Sold: + var lastAuctionBid = await GetLastAuctionBidByProductToAuctionIdAsync(productToAuction.Id); + if (lastAuctionBid == null) productToAuction.AuctionStatus = AuctionStatus.NotSold; + else + { + productToAuction.AuctionStatus = AuctionStatus.Sold; + productToAuction.CurrentPrice = lastAuctionBid.BidPrice; + productToAuction.WinnerCustomerId = lastAuctionBid.CustomerId; + + var placeOrderResult = await CreateOrderForWinnerAsync(productToAuction); + if (placeOrderResult == null || placeOrderResult.Id == 0) + { + logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); (placeOrderResult == null || placeOrderResult.Id == 0)", null, customer); + //return; //TODO: EGYELŐRE HAGYJUK LEZÁRNI AKKOR IS, HA NEM SIKERÜLT AZ ORDERPLACE()! - J. + } + } + + await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, auction.CategoryId, false); + break; + + case AuctionStatus.Pause: + productToAuction.AuctionStatus = AuctionStatus.Pause; + break; + + default: + logger.Error($"AuctionHub.UpdateProductToAuctionStatusIfValidAsync(); AuctionStatus not found; (newStatus == {newProductToAuctionStatus})", null, customer); + + return ResponseType.ToCaller; + } + + if (updateInDatabase) + await UpdateProductToAuctionMappingAsync(productToAuction); + } + + return ResponseType.ToAllClients; + } + + public async Task<(Auction auction, ProductToAuctionMapping productToAuction, ResponseType responseType)> GetAndUpdateProductToAuctionStatusIfValidAsync(int productToAuctionId, AuctionStatus newProductToAuctionStatus, Customer customer) + { + var productToAuction = await GetProductToAuctionMappingByIdAsync(productToAuctionId); + if (productToAuction == null) + { + logger.Error($"AuctionHub.GetAndUpdateProductToAuctionStatusIfValidAsync(); (productToAuction == null)", null, customer); + return (null, null, ResponseType.None); + } + + var auction = await GetAuctionByIdAsync(productToAuction.AuctionId); + if (auction == null || auction.Closed) + { + logger.Error($"AuctionHub.GetAndUpdateProductToAuctionStatusIfValidAsync(); (auction == null || auction.Closed); Closed: {auction?.Closed}", null, customer); + return (null, null, ResponseType.None); + } + + var responseType = await UpdateProductToAuctionStatusIfValidAsync(newProductToAuctionStatus, auction, productToAuction, customer); + return (auction, productToAuction, responseType); + } + + public async Task ResetProductToAuction(ProductToAuctionMapping productToAuction, int? categoryId = null) + { + productToAuction.AuctionStatus = AuctionStatus.None; + await ResetProductToAuctionAsync(productToAuction, productToAuction.StartingPrice); + + categoryId ??= (await GetAuctionByIdAsync(productToAuction.AuctionId))?.CategoryId; + await UpdateProductCategoryIsFeaturedAsync(productToAuction.ProductId, categoryId, false); + } + + public async Task UpdateProductCategoryIsFeaturedAsync(int productId, int? categoryId, bool isFeatured) + { + //Leszarjuk ha elszáll, az aukció menjen tovább... - J. + try + { + if (categoryId.GetValueOrDefault(0) == 0) return; + + var productCategory = (await categoryService.GetProductCategoriesByProductIdAsync(productId)).FirstOrDefault(x => x.CategoryId == categoryId); + if (productCategory == null) return; + + if (productCategory.IsFeaturedProduct == isFeatured) return; + + productCategory.IsFeaturedProduct = isFeatured; + await categoryService.UpdateProductCategoryAsync(productCategory); + } + catch (Exception ex) + { + logger.Error($"AuctionHub.UpdateProductCategoryIsFeaturedAsync(); categoryId: {categoryId}; productId: {productId}; isFeatured: {isFeatured}", ex); + } + } + + public bool IsValidRequestAuctionStatus(AuctionStatus newStatus, AuctionStatus oldStatus) + { + switch (oldStatus) + { + case AuctionStatus.None: + return newStatus is AuctionStatus.Active or AuctionStatus.Pause; + case AuctionStatus.Active: + return newStatus is AuctionStatus.FirstWarning or AuctionStatus.Pause; + case AuctionStatus.FirstWarning: + return newStatus is AuctionStatus.SecondWarning or AuctionStatus.Pause; + case AuctionStatus.SecondWarning: + return newStatus is AuctionStatus.Sold or AuctionStatus.Pause; + case AuctionStatus.Pause: + return newStatus is AuctionStatus.None or AuctionStatus.Active; + case AuctionStatus.Sold: + case AuctionStatus.NotSold: + default: + return false; + } + } + #endregion + #region Methods public static decimal GetStepAmount(decimal currentPrice) @@ -103,29 +240,35 @@ public class AuctionService( public Task ResetProductToAuctionAsync(ProductToAuctionMapping productToAuction, decimal basePrice = 0) => ctx.ResetProductToAuctionAsync(productToAuction, basePrice); - public Task GetLastAuctionBidByProductToAuctionIdAsync(int productToAuctionId) - => ctx.GetLastAuctionBidByProductToAuctionId(productToAuctionId); + public Task> GetAllLastBidByAuctionIdAsync(int auctionId) + => ctx.GetAllLastBidByAuctionIdAsync(auctionId); - public Task GetBidsCountByProductToAuctionIdAsync(int productToAuctionId) - => ctx.GetBidsCountByProductToAuctionIdAsync(productToAuctionId); + public Task> GetAllLastBidDictionaryByAuctionIdAsync(int auctionId) + => ctx.GetAllLastBidDictionaryByAuctionIdAsync(auctionId); - public Task HasBidByProductToAuctionIdAsync(int productToAuctionId) - => ctx.HasBidByProductToAuctionIdAsync(productToAuctionId); + public Task GetLastAuctionBidByProductToAuctionIdAsync(int productToAuctionId) + => ctx.GetLastAuctionBidByProductToAuctionId(productToAuctionId); - public Task RevertAuctionBidByProductToAuctionIdAsync(int productToAuctionId) - => ctx.RevertAuctionBidByProductToAuctionId(productToAuctionId); + public Task GetBidsCountByProductToAuctionIdAsync(int productToAuctionId) + => ctx.GetBidsCountByProductToAuctionIdAsync(productToAuctionId); - public async Task GetProductById(int productId) - { - var product = await productService.GetProductByIdAsync(productId); - if (product != null) return product; + public Task HasBidByProductToAuctionIdAsync(int productToAuctionId) + => ctx.HasBidByProductToAuctionIdAsync(productToAuctionId); - logger.Error($"AuctionService.GetProductById(); (product == null)", null, await workContext.GetCurrentCustomerAsync()); - return null; + public Task RevertAuctionBidByProductToAuctionIdAsync(int productToAuctionId) + => ctx.RevertAuctionBidByProductToAuctionId(productToAuctionId); - } + public async Task GetProductById(int productId) + { + var product = await productService.GetProductByIdAsync(productId); + if (product != null) return product; - /// + logger.Error($"AuctionService.GetProductById(); (product == null)", null, await workContext.GetCurrentCustomerAsync()); + return null; + + } + + /// /// Gets all bids /// /// The store identifier; pass 0 to load all records @@ -258,7 +401,7 @@ public class AuctionService( var winnerCustomer = await customerService.GetCustomerByIdAsync(productToAuction.WinnerCustomerId); var storeId = winnerCustomer.RegisteredInStoreId; - + var billingAddress = await InsertOrUpdateBillingAddressAsync(winnerCustomer); if (billingAddress == null) { @@ -386,6 +529,7 @@ public class AuctionService( } #region auctions + public async Task InsertAuctionAsync(Auction auction) { await ctx.Auctions.InsertAsync(auction, false); @@ -396,19 +540,20 @@ public class AuctionService( await ctx.Auctions.UpdateAsync(auction); } - public Task> GetAllAuctionsAsync() =>ctx.Auctions.GetAllAuctions().ToListAsync(); - public Task> GetAllCurrentAutoOpenAndClosedAuctionsAsync() =>ctx.Auctions.GetAllCurrentAutoOpenAndClosedAuctions().ToListAsync(); + public Task> GetAllAuctionsAsync() => ctx.Auctions.GetAllAuctions().ToListAsync(); + public Task> GetAllCurrentAutoOpenAndClosedAuctionsAsync() => ctx.Auctions.GetAllCurrentAutoOpenAndClosedAuctions().ToListAsync(); public async Task> GetProductToAuctionsByAuctionIdAsync(int auctionId, bool onlyActiveItems) => await ctx.ProductToAuctions.GetProductToAuctionsByAuctionId(auctionId, onlyActiveItems).OrderBy(x => x.SortIndex).ToListAsync(); - - public Task GetNextProductToAuctionByAuctionIdAsync(int auctionId) + + public Task GetNextProductToAuctionByAuctionIdAsync(int auctionId) => ctx.ProductToAuctions.GetNextItemByAuctionIdAsync(auctionId); public Task> GetNotClosedProductToAuctionsByAuctionId(int auctionId) => ctx.ProductToAuctions.GetNotClosedItemsByAuctionId(auctionId).OrderBy(x => x.SortIndex).ToListAsync(); #endregion + #endregion #region Dtos @@ -420,7 +565,7 @@ public class AuctionService( foreach (var auctionDtoProductToAuctionDto in auctionDto.ProductToAuctionDtos) { - auctionDtoProductToAuctionDto.AuctionBidDtos.AddRange(await ctx.AuctionBids.GetByProductToAuctionId(auctionDtoProductToAuctionDto.Id).OrderByDescending(x => x.Id).Take(maxBidsCount).Select(x => new AuctionBidDto(x)).ToListAsync()); + auctionDtoProductToAuctionDto.AuctionBidDtos.AddRange(await ctx.AuctionBids.GetAllByProductToAuctionId(auctionDtoProductToAuctionDto.Id).OrderByDescending(x => x.Id).Take(maxBidsCount).Select(x => new AuctionBidDto(x)).ToListAsync()); } return auctionDto; @@ -435,7 +580,7 @@ public class AuctionService( var auctionDto = new AuctionDto(auction); if (widthProducts) auctionDto.ProductToAuctionDtos.AddRange((await GetProductToAuctionDtosByAuctionId(auctionId, activeProductOnly))); - + return auctionDto; } @@ -474,22 +619,22 @@ public class AuctionService( public async Task> GetProductToAuctionDtosByProductIdAsync(int productId) { - return [..await ctx.ProductToAuctions.GetByProductId(productId).Select(x=>new ProductToAuctionDto(x)).ToListAsync()]; + return [..await ctx.ProductToAuctions.GetByProductId(productId).Select(x => new ProductToAuctionDto(x)).ToListAsync()]; } public async Task GetAuctionBidDtoByIdAsync(int auctionBidId) { var auctionBid = await ctx.AuctionBids.GetByIdAsync(auctionBidId); - + return auctionBid == null ? null : new AuctionBidDto(auctionBid); } - public Task> GetProductToAuctionsByProductIdAsync(int productId) + public Task> GetProductToAuctionsByProductIdAsync(int productId) => ctx.GetProductToAuctionsByProductIdAsync(productId); public Task> GetProductToAuctionByAuctionIdAndProductIdAsync(int auctionId, int productId, bool activeProductOnly) => ctx.GetProductToAuctionByAuctionIdAndProductIdAsync(auctionId, productId, activeProductOnly); - + public async Task AssignProductToAuctionAsync(int productId, decimal startingPrice, decimal bidPrice, int auctionId) { diff --git a/Nop.Plugin.Misc.AuctionPlugin/Services/IAuctionService.cs b/Nop.Plugin.Misc.AuctionPlugin/Services/IAuctionService.cs index a65c1be..05dfa1c 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Services/IAuctionService.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Services/IAuctionService.cs @@ -1,9 +1,11 @@ using Microsoft.AspNetCore.Mvc; using Nop.Core; +using Nop.Core.Domain.Customers; using Nop.Core.Domain.Orders; using Nop.Plugin.Misc.AuctionPlugin.Domains; using Nop.Plugin.Misc.AuctionPlugin.Domains.Dtos; using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities; +using Nop.Plugin.Misc.AuctionPlugin.Domains.Enums; using Nop.Services.Orders; namespace Nop.Plugin.Misc.AuctionPlugin.Services; @@ -14,7 +16,11 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Services; public interface IAuctionService { //decimal GetStepAmount(decimal currentPrice); - + Task UpdateProductToAuctionStatusIfValidAsync(AuctionStatus newProductToAuctionStatus, Auction auction, ProductToAuctionMapping productToAuction, Customer customer, bool updateInDatabase = true); + Task<(Auction auction, ProductToAuctionMapping productToAuction, ResponseType responseType)> GetAndUpdateProductToAuctionStatusIfValidAsync(int productToAuctionId, AuctionStatus newProductToAuctionStatus, Customer customer); + Task ResetProductToAuction(ProductToAuctionMapping productToAuction, int? categoryId = null); + Task UpdateProductCategoryIsFeaturedAsync(int productId, int? categoryId, bool isFeatured); + bool IsValidRequestAuctionStatus(AuctionStatus newStatus, AuctionStatus oldStatus); /// /// Gets all bids @@ -29,6 +35,8 @@ public interface IAuctionService Task> GetAllBidsAsync(int customerId = 0, int pageIndex = 0, int pageSize = int.MaxValue); Task GetBidsCountByProductToAuctionIdAsync(int productToAuctionId); + Task> GetAllLastBidByAuctionIdAsync(int auctionId); + Task> GetAllLastBidDictionaryByAuctionIdAsync(int auctionId); Task HasBidByProductToAuctionIdAsync(int productToAuctionId); Task GetBidByIdAsync(int bidId);