diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs index 2a599a7..0b869af 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionBidDbTable.cs @@ -15,13 +15,35 @@ public class AuctionBidDbTable : MgDbTableBase { } - public Task GetLastAuctionBidByProductToAuctionIdAsync(int prouctToAuctionId) + public IQueryable GetLastAuctionBidByProductToAuctionId(int productToAuctionId) + => GetByProductToAuctionId(productToAuctionId).OrderByDescending(x => x.Id); + + public IQueryable GetByProductToAuctionId(int productToAuctionId) + => Table.Where(x => x.ProductAuctionMappingId == productToAuctionId); + + public Task HasBidByProductToAuctionIdAsync(int productToAuctionId) { - return Table.Where(x => x.ProductAuctionMappingId == prouctToAuctionId).OrderByDescending(x => x.Id).FirstOrDefaultAsync(); + return Table.AnyAsync(x => x.ProductAuctionMappingId == productToAuctionId); } - public IQueryable GetByProductToAuctionIdAsync(int prouctToAuctionId) + public async Task RevertByProductToAuctionIdAsync(int productToAuctionId) { - return Table.Where(x => x.ProductAuctionMappingId == prouctToAuctionId); + var lastBid = await GetLastAuctionBidByProductToAuctionId(productToAuctionId).FirstOrDefaultAsync(); + if (lastBid == null) + { + await Logger.InformationAsync($"AuctionBidDbTable.RevertByProductToAuctionIdAsync(); (lastBid == null); productToAuction.Id: {productToAuctionId}"); + return null; + } + + await DeleteAsync(lastBid); + return await GetLastAuctionBidByProductToAuctionId(productToAuctionId).FirstOrDefaultAsync(); + } + + public async Task DeleteAllByProductToAuctionIdAsync(int productToAuctionId) + { + var deletedBids = await DeleteAsync(x => x.ProductAuctionMappingId == productToAuctionId); + await Logger.InformationAsync($"AuctionBidDbTable.DeleteAllByProductToAuctionIdAsync(); productToAuction.Id: {productToAuctionId}; deletedBids: {deletedBids}"); + + return deletedBids; } } \ No newline at end of file diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs index cc514b8..f70e988 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/AuctionDbContext.cs @@ -1,14 +1,19 @@ using Mango.Nop.Core.Repositories; using Nop.Core; +using Nop.Core.Caching; using Nop.Data; using Nop.Plugin.Misc.AuctionPlugin.Domains.DataLayer.Interfaces; using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities; +using Nop.Services.Catalog; using System; +using Nop.Services.Logging; namespace Nop.Plugin.Misc.AuctionPlugin.Domains.DataLayer; public class AuctionDbContext : MgDbContextBase, IAuctionDbSet, IProductToAuctionDbSet, IAuctionBidDbSet { + private readonly IProductService _productService; + public AuctionDbTable Auctions { get; set; } public ProductToAuctionDbTable ProductToAuctions { get; set; } public AuctionBidDbTable AuctionBids { get; set; } @@ -18,8 +23,10 @@ public class AuctionDbContext : MgDbContextBase, IAuctionDbSet, //public IRepository AuctionBids2 { get; set; } - public AuctionDbContext(INopDataProvider dataProvider, AuctionDbTable auctionDbTable, ProductToAuctionDbTable productToAuctionDbTable, AuctionBidDbTable auctionBidDbTable) : base(dataProvider) + public AuctionDbContext(INopDataProvider dataProvider, AuctionDbTable auctionDbTable, ProductToAuctionDbTable productToAuctionDbTable, AuctionBidDbTable auctionBidDbTable, IProductService productService, ILogger logger) : base(dataProvider, logger) { + _productService = productService; + Auctions = auctionDbTable; ProductToAuctions = productToAuctionDbTable; AuctionBids = auctionBidDbTable; @@ -44,4 +51,42 @@ public class AuctionDbContext : MgDbContextBase, IAuctionDbSet, return [..await ProductToAuctions.GetByAuctionAndProductId(auctionId, productId, activeProductOnly).ToListAsync()]; } + public Task HasBidByProductToAuctionIdAsync(int productToAuctionId) + => AuctionBids.HasBidByProductToAuctionIdAsync(productToAuctionId); + + public Task GetLastAuctionBidByProductToAuctionId(int productToAuctionId) + => AuctionBids.GetLastAuctionBidByProductToAuctionId(productToAuctionId).FirstOrDefaultAsync(); + + public Task RevertAuctionBidByProductToAuctionId(int productToAuctionId) + => AuctionBids.RevertByProductToAuctionIdAsync(productToAuctionId); + + public async Task ResetProductToAuctionByProductId(int productId) + => await ResetProductToAuctionAsync(await ProductToAuctions.GetByProductId(productId).FirstOrDefaultAsync()); + + public async Task ResetProductToAuctionByIdAsync(int productToAuctionId, decimal basePrice = 0) + => await ResetProductToAuctionAsync(ProductToAuctions.GetById(productToAuctionId), basePrice); + + public async Task ResetProductToAuctionAsync(ProductToAuctionMapping productToAuction, decimal basePrice = 0) + { + if (productToAuction == null) + { + Logger.Error($"AuctionDbContext.ResetProductToAuctionAsync(); productToAuction == null"); + return; + } + + await Logger.InformationAsync($"AuctionDbContext.ResetProductToAuctionAsync(); productToAuction.Id: {productToAuction.Id}; basePrice: {basePrice}"); + + var product = await _productService.GetProductByIdAsync(productToAuction.ProductId); + if (product == null) + { + Logger.Error($"AuctionDbContext.ResetProductToAuctionAsync(); product == null"); + return; + } + + if (basePrice <= 0) basePrice = product.Price; + else product.Price = basePrice; + + await ProductToAuctions.ResetAsync(productToAuction, basePrice); + await AuctionBids.DeleteAllByProductToAuctionIdAsync(productToAuction.Id); + } } \ No newline at end of file diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/ProductToAuctionDbTable.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/ProductToAuctionDbTable.cs index 4a1323f..c652770 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/ProductToAuctionDbTable.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/DataLayer/ProductToAuctionDbTable.cs @@ -44,16 +44,18 @@ public class ProductToAuctionDbTable : MgDbTableBase (!activeProductOnly || x.AuctionStatus == AuctionStatus.Active || x.AuctionStatus == AuctionStatus.FirstWarning || x.AuctionStatus == AuctionStatus.SecondWarning /*HasActiveAuctionStatus(x.AuctionStatus)*/)); } - public async Task DeactivateItemByProductId(int productId, decimal basePrice) => await DeactivateItem(await GetByProductId(productId).FirstOrDefaultAsync(), basePrice); - public async Task DeactivateItemById(int productToAuctionId, decimal basePrice) => await DeactivateItem(await GetByIdAsync(productToAuctionId), basePrice); - public async Task DeactivateItem(ProductToAuctionMapping productToAuction, decimal basePrice) + public async Task ResetByProductIdAsync(int productId, decimal basePrice) => await ResetAsync(await GetByProductId(productId).FirstOrDefaultAsync(), basePrice); + public async Task ResetByIdAsync(int productToAuctionId, decimal basePrice) => await ResetAsync(await GetByIdAsync(productToAuctionId), basePrice); + public async Task ResetAsync(ProductToAuctionMapping productToAuction, decimal basePrice) { if (productToAuction == null) { - Logger.Error($"ProductToAuctionDbTable.DeactivateItem(); productToAuction == null"); + Logger.Error($"ProductToAuctionDbTable.ResetAsync(); productToAuction == null"); return; } + await Logger.InformationAsync($"ProductToAuctionDbTable.ResetAsync(); productToAuction.Id: {productToAuction.Id}; basePrice: {basePrice}"); + //TODO: ezt kivegyem egyelőre? amíg a Product.Price-t használjuk, addig nem sok értelme productToAuction.StartingPrice = basePrice; productToAuction.CurrentPrice = basePrice; diff --git a/Nop.Plugin.Misc.AuctionPlugin/Domains/EventConsumers/AuctionEventConsumer.cs b/Nop.Plugin.Misc.AuctionPlugin/Domains/EventConsumers/AuctionEventConsumer.cs index aca55b1..90083a6 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Domains/EventConsumers/AuctionEventConsumer.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Domains/EventConsumers/AuctionEventConsumer.cs @@ -1,23 +1,31 @@ -using Mango.Nop.Services; +using DocumentFormat.OpenXml.Office2010.Drawing; +using Mango.Nop.Services; using Microsoft.AspNetCore.Http; using Nop.Core.Domain.Catalog; using Nop.Core.Events; using Nop.Plugin.Misc.AuctionPlugin.Domains.DataLayer; using Nop.Plugin.Misc.AuctionPlugin.Domains.Enums; +using Nop.Services.Logging; namespace Nop.Plugin.Misc.AuctionPlugin.Domains.EventConsumers; -public class AuctionEventConsumer(IHttpContextAccessor httpContextAccessor, AuctionDbContext ctx) : MgEventConsumer(httpContextAccessor) +public class AuctionEventConsumer(IHttpContextAccessor httpContextAccessor, ILogger logger, AuctionDbContext ctx) : MgEventConsumer(httpContextAccessor, logger) { public override async Task HandleEventAsync(EntityUpdatedEvent eventMessage) { - //TODO: itt lehetne ciklussal az összes ProductToAuction-re! - J. - var productToAuction = await ctx.ProductToAuctions.GetByProductId(eventMessage.Entity.Id).FirstOrDefaultAsync(); + await Logger.InformationAsync($"AuctionEventConsumer.HandleEventAsync();"); - //foreach - if (productToAuction is { AuctionStatus: AuctionStatus.None }) + var productToAuctions = await ctx.ProductToAuctions.GetByProductId(eventMessage.Entity.Id).Where(x => x.AuctionStatus == AuctionStatus.None).ToListAsync(); + + foreach (var productToAuction in productToAuctions) { - await ctx.ProductToAuctions.DeactivateItem(productToAuction, eventMessage.Entity.Price); + if (await ctx.HasBidByProductToAuctionIdAsync(productToAuction.Id)) + { + await Logger.InformationAsync($"AuctionEventConsumer.HandleEventAsync(); HasAuctionBids->continue"); + continue; + } + + await ctx.ProductToAuctions.ResetAsync(productToAuction, eventMessage.Entity.Price); } await base.HandleEventAsync(eventMessage); diff --git a/Nop.Plugin.Misc.AuctionPlugin/Hubs/Messages/AuctionBidRequest.cs b/Nop.Plugin.Misc.AuctionPlugin/Hubs/Messages/AuctionBidRequest.cs index 2bf41e8..a0c217e 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Hubs/Messages/AuctionBidRequest.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Hubs/Messages/AuctionBidRequest.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Nop.Plugin.Misc.AuctionPlugin.Domains.Dtos; +using Nop.Plugin.Misc.AuctionPlugin.Domains.Dtos; -namespace Nop.Plugin.Misc.AuctionPlugin.Models +namespace Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages { public class AuctionBidRequest : AuctionBidDto { diff --git a/Nop.Plugin.Misc.AuctionPlugin/Hubs/Messages/RevertAuctionBidRequest.cs b/Nop.Plugin.Misc.AuctionPlugin/Hubs/Messages/RevertAuctionBidRequest.cs new file mode 100644 index 0000000..d3a9a76 --- /dev/null +++ b/Nop.Plugin.Misc.AuctionPlugin/Hubs/Messages/RevertAuctionBidRequest.cs @@ -0,0 +1,6 @@ +namespace Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages; + +public class RevertAuctionBidRequest +{ + public int ProductToAuctionId { get; set; } +} \ No newline at end of file diff --git a/Nop.Plugin.Misc.AuctionPlugin/Hubs/SignalRMessageHandler.cs b/Nop.Plugin.Misc.AuctionPlugin/Hubs/SignalRMessageHandler.cs index 1d2aacd..948eab8 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Hubs/SignalRMessageHandler.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Hubs/SignalRMessageHandler.cs @@ -7,7 +7,12 @@ using Nop.Services.Catalog; using Nop.Services.Logging; using Microsoft.AspNetCore.SignalR; using Nop.Core; +using Nop.Core.Domain.Catalog; using Nop.Plugin.Misc.AuctionPlugin.Domains.Enums; +using Nop.Core.Domain.Customers; +using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities; +using Nop.Services.Customers; +using DocumentFormat.OpenXml.Wordprocessing; namespace Nop.Plugin.Misc.AuctionPlugin.Hubs { @@ -23,23 +28,25 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs //- ha bid-elt 1x is, kerüljön a watch-ba //- DbTransaction-t vhogy megcsinánli! - public class SignalRMessageHandler(ILogger logger, IProductService productService, AuctionService auctionService, IHubContext hubContext, IWorkContext workContext) + public class SignalRMessageHandler(ILogger logger, IProductService productService, AuctionService auctionService, IHubContext hubContext, IWorkContext workContext, ICustomerService customerService) { private readonly Mutex _handleMessageMutex = new(); public async Task HandleMessage(MessageWrapper message) { + var customer = await workContext.GetCurrentCustomerAsync(); + if (message?.Data == null) { - logger.Error($"SignalRMessageHandler.HandleMessage(); message?.Data == null"); + logger.Error($"SignalRMessageHandler.HandleMessage(); message?.Data == null", null, customer); return; } - await logger.InformationAsync($"SignalRMessageHandler.HandleMessage(); jsonData: {message.Data}"); + await logger.InformationAsync($"SignalRMessageHandler.HandleMessage(); jsonData: {message.Data}", null, customer); - if (message.SenderId <= 0 || message.SenderId != (await workContext.GetCurrentCustomerAsync()).Id) + if (customer == null || message.SenderId <= 0 || message.SenderId != customer.Id || await customerService.IsGuestAsync(customer)) { - logger.Error($"SignalRMessageHandler.HandleMessage(); message.SenderId <= 0 || message.SenderId != (await _workContext.GetCurrentCustomerAsync()).Id; SenderId: {message.SenderId}"); + logger.Error($"SignalRMessageHandler.HandleMessage(); (customer == null || message.SenderId <= 0 || message.SenderId != customer.Id || IsGuestAsync() == true)", null, customer); return; } @@ -47,74 +54,118 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs { try { - switch (message.MessageType) + if (message.MessageType == "BidRequestMessage") await HandleBidRequest(customer, message.Data.JsonTo()); + else { - case "BidRequestMessage": - await HandleBidRequest(message.SenderId, message.Data.JsonTo()); - break; + if (!await customerService.IsAdminAsync(customer)) + { + logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); IsAdminAsync() == false!", null, customer); + return; + } - case "AuctionProductStatusRequest": - await HandleProductToAuctionStatusChangedRequest(message.SenderId, message.Data.JsonTo()); - break; + switch (message.MessageType) + { + case nameof(AuctionProductStatusRequest): + await HandleProductToAuctionStatusChangedRequest(customer, message.Data.JsonTo()); + break; - // Add other message types here - default: - await logger.ErrorAsync($"SignalRMessageHandler.HandleMessage(); Unknown message type; MessageType: {message.MessageType}"); - break; + case nameof(RevertAuctionBidRequest): + await HandleRevertAuctionBidRequest(customer, message.Data.JsonTo()); + break; + + default: + // Add other message types here + await logger.ErrorAsync($"SignalRMessageHandler.HandleMessage(); Unknown message type; MessageType: {message.MessageType}", null, customer); + break; + } } } catch (Exception ex) { - logger.Error($"SignalRMessageHandler.HandleMessage(); switch (message.MessageType); MessageType: {message.MessageType}; ex: {ex}"); + logger.Error($"SignalRMessageHandler.HandleMessage(); switch (message.MessageType); MessageType: {message.MessageType}; Exception: {ex.Message}", ex, customer); } } } - private async Task HandleProductToAuctionStatusChangedRequest(int senderId, AuctionProductStatusRequest auctionProductStatusRequest) + private async Task HandleRevertAuctionBidRequest(Customer customer, RevertAuctionBidRequest revertAuctionBidRequest) { - if (auctionProductStatusRequest == null) + if (revertAuctionBidRequest == null) { - logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); auctionProductStatusRequest == null"); + logger.Error($"SignalRMessageHandler.HanldeRevertAuctionBidRequest(); auctionProductStatusRequest == null", null, customer); return; } try { - await logger.InformationAsync($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); ProductToAuctionMappingId: {auctionProductStatusRequest.ProductToAuctionId}; Status: {auctionProductStatusRequest.AuctionStatus}({(int)auctionProductStatusRequest.AuctionStatus})"); + var productToAuction = (await auctionService.GetProductToAuctionMappingByIdAsync(revertAuctionBidRequest.ProductToAuctionId)); + if (productToAuction is not { AuctionStatus: AuctionStatus.Pause }) + { + logger.Warning($"SignalRMessageHandler.HandleBidRequest(); (productToAuction is not {{ AuctionStatus: AuctionStatus.Pause }}); AuctionStatus: {productToAuction?.AuctionStatus}", null, customer); + return; //TODO: - J. + } - //TODO: if IsAdmin.. - J. - //productBidBoxViewModel.IsAdmin = await _customerService.IsAdminAsync(customer); - //productBidBoxViewModel.IsGuest = await _customerService.IsGuestAsync(customer); + var product = await auctionService.GetProductById(productToAuction.ProductId); + if (product == null) return; - //TODO: if nincs aktív item.. - J. + var revertLastBid = await auctionService.RevertAuctionBidByProductToAuctionIdAsync(productToAuction.Id); + if (revertLastBid == null) + { + //TODO: NA ILYENKOR VAN A CUMI... - J. + return; + } + + await SetAuctionBidPrice(revertLastBid.BidPrice, productToAuction, product); + await SendAuctionBidMessageAsync(revertLastBid, productToAuction, product, customer.Id); + } + catch (Exception ex) + { + logger.Error($"SignalRMessageHandler.HanldeRevertAuctionBidRequest(); Exception: {ex.Message}", ex, customer); + } + } + + private async Task HandleProductToAuctionStatusChangedRequest(Customer customer, AuctionProductStatusRequest auctionProductStatusRequest) + { + if (auctionProductStatusRequest == null) + { + logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); auctionProductStatusRequest == null", null, customer); + return; + } + + try + { + await logger.InformationAsync($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); ProductToAuctionMappingId: {auctionProductStatusRequest.ProductToAuctionId}; Status: {auctionProductStatusRequest.AuctionStatus}({(int)auctionProductStatusRequest.AuctionStatus})", null, customer); var auction = await auctionService.GetAuctionDtoByProductToAuctionIdAsync(auctionProductStatusRequest.ProductToAuctionId, false); if (auction == null || auction.Closed) { - logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); (auction == null || auction.Closed); Closed: {auction?.Closed}"); + logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); (auction == null || auction.Closed); Closed: {auction?.Closed}", null, customer); return; } var productToAuction = await auctionService.GetProductToAuctionMappingByIdAsync(auctionProductStatusRequest.ProductToAuctionId); if (productToAuction == null) { - logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); (productToAuction == null)"); + logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); (productToAuction == null)", null, customer); + return; + } + + if (!IsValidRequestAuctionStatus(auctionProductStatusRequest.AuctionStatus, productToAuction.AuctionStatus)) + { + logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); RequestAuctionStatusIsValid() == false; newStatus: {auctionProductStatusRequest.AuctionStatus}; oldStatus: {productToAuction.AuctionStatus}", null, customer); return; } - //TODO: mi van ha már lezárt a productToAuction? - J. if (auctionProductStatusRequest.AuctionStatus == AuctionStatus.None) { - //TODO: a ProductPrice-t ne változtassuk, mert emiatt nem jó a reset! - J. productToAuction.AuctionStatus = AuctionStatus.None; - await auctionService.DeactivateProductToAuctionAsync(productToAuction); //TODO: Reset legyen és ne deactivate! - J. + await auctionService.ResetProductToAuctionAsync(productToAuction, productToAuction.StartingPrice); } else { switch (auctionProductStatusRequest.AuctionStatus) { - case AuctionStatus.Pause: - //TODO: Pause - J. + case AuctionStatus.Pause: + productToAuction.AuctionStatus = AuctionStatus.Pause; break; case AuctionStatus.Sold: @@ -126,11 +177,12 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs } productToAuction.AuctionStatus = AuctionStatus.Sold; + productToAuction.CurrentPrice = lastAuctionBid.BidPrice; productToAuction.WinnerCustomerId = lastAuctionBid.CustomerId; break; case AuctionStatus.NotSold: - logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); (auctionProductStatusRequest.AuctionStatus == AuctionStatus.NotSold)"); + logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); (auctionProductStatusRequest.AuctionStatus == AuctionStatus.NotSold)", null, customer); break; case AuctionStatus.FirstWarning: @@ -147,7 +199,7 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs var productToauctionChangedNotification = new MessageWrapper { MessageType = nameof(ProductToAuctionStatusNotification), - SenderId = senderId, + SenderId = customer.Id, Data = new ProductToAuctionStatusNotification(await auctionService.GetAuctionDtoByProductToAuctionIdAsync(productToAuction.Id, true)) { ToasterMessage = "EMPTY", //TODO: - J. @@ -158,52 +210,38 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs } catch (Exception ex) { - logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); Error {ex.Message}"); + logger.Error($"SignalRMessageHandler.HandleProductToAuctionStatusChangedRequest(); Exception: {ex.Message}", ex, customer); } - } - private async Task HandleBidRequest(int senderId, AuctionBidRequest bidRequestMessage) + private async Task HandleBidRequest(Customer customer, AuctionBidRequest bidRequestMessage) { if (bidRequestMessage == null) { - logger.Error($"SignalRMessageHandler.HandleBidRequest(); (bidRequestMessage == null)"); + logger.Error($"SignalRMessageHandler.HandleBidRequest(); (bidRequestMessage == null)", null, customer); return; } try { - await logger.InformationAsync($"SignalRMessageHandler.HandleBidRequest(); Bid received; Auction: {bidRequestMessage.AuctionId}; Product: {bidRequestMessage.ProductId}; Bid: {bidRequestMessage.BidPrice}; Customer: {bidRequestMessage.CustomerId}"); - - //CustomerService a = new CustomerService()a.IsGuestAsync() //TODO: IsGuestAsync??? - J. - - var customer = await workContext.GetCurrentCustomerAsync(); - if (customer == null || bidRequestMessage.CustomerId != customer.Id) //|| !customer.Active) - { - logger.Error($"SignalRMessageHandler.HandleBidRequest(); (customer == null || bidRequestMessage.CustomerId != customer.Id)"); - return; - } + await logger.InformationAsync($"SignalRMessageHandler.HandleBidRequest(); Bid received; Auction: {bidRequestMessage.AuctionId}; ProductToAuction: {bidRequestMessage.ProductAuctionMappingId}; Product: {bidRequestMessage.ProductId}; Bid: {bidRequestMessage.BidPrice}; Customer: {bidRequestMessage.CustomerId}", null, customer); var auction = await auctionService.GetAuctionDtoByIdAsync(bidRequestMessage.AuctionId, false, false); if (auction == null || auction.Closed) { - logger.Warning($"SignalRMessageHandler.HandleBidRequest(); (auction == null || auction.Closed); Closed: {auction?.Closed}"); + logger.Warning($"SignalRMessageHandler.HandleBidRequest(); (auction == null || auction.Closed); Closed: {auction?.Closed}", null, customer); return; } var activeProductAuction = (await auctionService.GetProductToAuctionByAuctionIdAndProductIdAsync(bidRequestMessage.AuctionId, bidRequestMessage.ProductId, true)).FirstOrDefault(); if (activeProductAuction is not { IsActiveItem: true } || activeProductAuction.WinnerCustomerId == customer.Id) { - logger.Warning($"SignalRMessageHandler.HandleBidRequest(); (activeProductAuction is not {{ IsActiveItem: true }} || activeProductAuction.WinnerCustomerId == customer.Id); AuctionStatus: {activeProductAuction?.AuctionStatus}; WinnerCustomerId: {activeProductAuction?.WinnerCustomerId}"); + logger.Warning($"SignalRMessageHandler.HandleBidRequest(); (activeProductAuction is not {{ IsActiveItem: true }} || activeProductAuction.WinnerCustomerId == customer.Id); AuctionStatus: {activeProductAuction?.AuctionStatus}; WinnerCustomerId: {activeProductAuction?.WinnerCustomerId}", null, customer); return; //TODO: - J. } - var product = await productService.GetProductByIdAsync(bidRequestMessage.ProductId); - if (product == null) - { - logger.Error($"SignalRMessageHandler.HandleBidRequest(); (product == null)"); - return; //ha nincs product vagy exception van, akkor ne broadcast-eljük ki az invalid Bid-et! - J. - } + var product = await auctionService.GetProductById(bidRequestMessage.ProductId); + if (product == null) return; var auctionBid = bidRequestMessage.CreateMainEntity(); auctionBid.ProductAuctionMappingId = activeProductAuction.Id; @@ -211,45 +249,85 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs //TODO: validate the bidprice amount if (product.Price >= auctionBid.BidPrice || activeProductAuction.CurrentPrice >= auctionBid.BidPrice) { - logger.Warning($"SignalRMessageHandler.HandleBidRequest(); (product.Price >= bidRequestMessage.BidPrice || activeProductAuction.CurrentPrice >= auctionBid.BidPrice); productPrice: {product.Price}; bidRequestPrice: {auctionBid.BidPrice}; activeProductAuctionPrice: {activeProductAuction.CurrentPrice}"); + logger.Warning($"SignalRMessageHandler.HandleBidRequest(); (product.Price >= bidRequestMessage.BidPrice || activeProductAuction.CurrentPrice >= auctionBid.BidPrice); productPrice: {product.Price}; bidRequestPrice: {auctionBid.BidPrice}; activeProductAuctionPrice: {activeProductAuction.CurrentPrice}", null, customer); return; } //save bid await auctionService.InsertBidAsync(auctionBid); - //set new price - product.Price = bidRequestMessage.BidPrice; - await productService.UpdateProductAsync(product); - - activeProductAuction.StartingPrice = product.OldPrice; - activeProductAuction.CurrentPrice = product.Price; activeProductAuction.AuctionStatus = AuctionStatus.Active; - - await auctionService.UpdateProductToAuctionMappingAsync(activeProductAuction); - - var stepAmount = AuctionService.GetStepAmount(auctionBid.BidPrice); - var nextBidPrice = auctionBid.BidPrice + stepAmount; - - var bid = new MessageWrapper - { - MessageType = "bidNotification", - SenderId = senderId, - Data = new BidNotificationMessage(await auctionService.GetAuctionDtoByProductToAuctionIdAsync(activeProductAuction.Id, true)) - { - ProductName = auctionBid.ProductId.ToString(), - CurrentPrice = auctionBid.BidPrice, - NextStepAmount = stepAmount, - NextBidPrice = nextBidPrice, - ToasterMessage = "EMPTY", //TODO: - J. - }.ToJson() - }; - - await hubContext.Clients.All.SendAsync("send", bid.ToJson()); + if (!await SetAuctionBidPrice(bidRequestMessage.BidPrice, activeProductAuction, product)) return; + + await SendAuctionBidMessageAsync(auctionBid, activeProductAuction, product, customer.Id); } catch (Exception ex) { - logger.Error($"SignalRMessageHandler.HandleBidRequest(); MessageHandling error: {ex}"); + logger.Error($"SignalRMessageHandler.HandleBidRequest(); Exception: {ex.Message}", ex, customer); + } + } + + private async Task SendAuctionBidMessageAsync(AuctionBid auctionBid, ProductToAuctionMapping productToAuction, Product product, int customerId) + { + var stepAmount = AuctionService.GetStepAmount(auctionBid.BidPrice); + var nextBidPrice = auctionBid.BidPrice + stepAmount; + + var bidMessage = new MessageWrapper + { + MessageType = "bidNotification", + SenderId = customerId, + Data = new BidNotificationMessage(await auctionService.GetAuctionDtoByProductToAuctionIdAsync(productToAuction.Id, true)) //TODO: NE KÉRJÜK LE DB-BŐL!!! - j. + { + ProductName = product.Name, + CurrentPrice = auctionBid.BidPrice, + NextStepAmount = stepAmount, + NextBidPrice = nextBidPrice, + ToasterMessage = "EMPTY", //TODO: - J. + }.ToJson() + }; + + await hubContext.Clients.All.SendAsync("send", bidMessage.ToJson()); + } + + private async Task SetAuctionBidPrice(decimal bidPrice, ProductToAuctionMapping productToAuction, Product product) + { + try + { + product.Price = bidPrice; + await productService.UpdateProductAsync(product); + + //activeProductAuction.StartingPrice = product.OldPrice; //TODO: ez biztosan kezelve van mikor összerendeljük? - J. + productToAuction.CurrentPrice = product.Price; + await auctionService.UpdateProductToAuctionMappingAsync(productToAuction); + + return true; + } + catch (Exception ex) + { + logger.Error($"SignalRMessageHandler.HandleBidRequest(); SetAuctionBidPrice() == false", ex); + } + + return false; + } + + private static bool IsValidRequestAuctionStatus(AuctionStatus newStatus, AuctionStatus oldStatus) + { + switch (oldStatus) + { + case AuctionStatus.None: + return newStatus == AuctionStatus.Active; + case AuctionStatus.Active: + return newStatus is AuctionStatus.None or AuctionStatus.FirstWarning or AuctionStatus.Pause; + case AuctionStatus.FirstWarning: + return newStatus is AuctionStatus.None or AuctionStatus.SecondWarning or AuctionStatus.Pause; + case AuctionStatus.SecondWarning: + return newStatus is AuctionStatus.None or 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; } } } diff --git a/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs b/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs index 68e0afe..b87d786 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs +++ b/Nop.Plugin.Misc.AuctionPlugin/Services/AuctionService.cs @@ -1,10 +1,12 @@ using Nop.Core; using Nop.Core.Caching; using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Customers; using Nop.Plugin.Misc.AuctionPlugin.Domains.DataLayer; using Nop.Plugin.Misc.AuctionPlugin.Domains.Dtos; using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities; using Nop.Plugin.Misc.AuctionPlugin.Domains.Enums; +using Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages; using Nop.Services.Catalog; using Nop.Services.Logging; using Org.BouncyCastle.Crypto; @@ -52,6 +54,7 @@ public class AuctionService : IAuctionService public AuctionService( AuctionDbContext ctx, IProductService productService, + //IRepository auctionRepository, //IRepository productToAuctionRepository, IShortTermCacheManager shortTermCacheManager, @@ -124,27 +127,31 @@ public class AuctionService : IAuctionService return true; } - public async Task DeactivateProductToAuctionByProductId(int productId) - => await DeactivateProductToAuctionAsync(await _ctx.ProductToAuctions.GetByProductId(productId).FirstOrDefaultAsync()); + public async Task ResetProductToAuctionByProductId(int productId) + => await ResetProductToAuctionAsync(await _ctx.ProductToAuctions.GetByProductId(productId).FirstOrDefaultAsync()); - public async Task DeactivateProductToAuctionByIdAsync(int productToAuctionId, decimal basePrice = 0) - => await DeactivateProductToAuctionAsync(_ctx.ProductToAuctions.GetById(productToAuctionId), basePrice); + public Task ResetProductToAuctionByIdAsync(int productToAuctionId, decimal basePrice = 0) + => ResetProductToAuctionAsync(_ctx.ProductToAuctions.GetById(productToAuctionId), basePrice); - public async Task DeactivateProductToAuctionAsync(ProductToAuctionMapping productToAuction, decimal basePrice = 0) + public Task ResetProductToAuctionAsync(ProductToAuctionMapping productToAuction, decimal basePrice = 0) + => _ctx.ResetProductToAuctionAsync(productToAuction, basePrice); + + public Task GetLastAuctionBidByProductToAuctionIdAsync(int productToAuctionId) + => _ctx.GetLastAuctionBidByProductToAuctionId(productToAuctionId); + + public Task RevertAuctionBidByProductToAuctionIdAsync(int productToAuctionId) + => _ctx.RevertAuctionBidByProductToAuctionId(productToAuctionId); + + public async Task GetProductById(int productId) { - if (basePrice <= 0) - { - var product = await _productService.GetProductByIdAsync(productToAuction.ProductId); + var product = await _productService.GetProductByIdAsync(productId); + if (product != null) return product; - if (product == null) _logger.Error($"AuctionService.DeactivateProductToAuctionByIdAsync(); product == null"); - else basePrice = product.Price; - } + _logger.Error($"AuctionService.GetProductById(); (product == null)", null, await _workContext.GetCurrentCustomerAsync()); + return null; - await _ctx.ProductToAuctions.DeactivateItem(productToAuction, basePrice); } - public Task GetLastAuctionBidByProductToAuctionIdAsync(int productToAuctionId) => _ctx.AuctionBids.GetLastAuctionBidByProductToAuctionIdAsync(productToAuctionId); - /// /// Gets all bids /// @@ -240,7 +247,7 @@ public class AuctionService : IAuctionService foreach (var auctionDtoProductToAuctionDto in auctionDto.ProductToAuctionDtos) { - auctionDtoProductToAuctionDto.AuctionBidDtos.AddRange(await _ctx.AuctionBids.GetByProductToAuctionIdAsync(auctionDtoProductToAuctionDto.Id).OrderByDescending(x => x.Id).Select(x => new AuctionBidDto(x)).ToListAsync()); + auctionDtoProductToAuctionDto.AuctionBidDtos.AddRange(await _ctx.AuctionBids.GetByProductToAuctionId(auctionDtoProductToAuctionDto.Id).OrderByDescending(x => x.Id).Select(x => new AuctionBidDto(x)).ToListAsync()); } return auctionDto; diff --git a/Nop.Plugin.Misc.AuctionPlugin/Views/PublicProductBidBox.cshtml b/Nop.Plugin.Misc.AuctionPlugin/Views/PublicProductBidBox.cshtml index 90da6d2..571772e 100644 --- a/Nop.Plugin.Misc.AuctionPlugin/Views/PublicProductBidBox.cshtml +++ b/Nop.Plugin.Misc.AuctionPlugin/Views/PublicProductBidBox.cshtml @@ -148,7 +148,7 @@ document.getElementById("signalRCloseItemButton").disabled = true; event.preventDefault(); - handleAuctionStatusChange(AuctionStatus.Sold); //Itt SoldOut volt, átírtam Sold-ra! - J. + handleAuctionStatusChange(AuctionStatus.None); //Itt SoldOut volt, átírtam Sold-ra! - J. return false; });