using Nop.Core;
using Nop.Core.Domain.Catalog;
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.Services.Catalog;
using Nop.Services.Logging;
using Nop.Services.Orders;
using Nop.Services.Payments;
namespace Nop.Plugin.Misc.AuctionPlugin.Services;
///
/// Store pickup point service
///
public class AuctionService : IAuctionService
{
#region Fields
private readonly AuctionDbContext _ctx;
private readonly IProductService _productService;
private readonly IWorkContext _workContext;
private readonly IPaymentService _paymentService;
private readonly IOrderProcessingService _orderProcessingService;
private readonly IShoppingCartService _shoppingCartService;
private readonly IStoreContext _storeContext;
private readonly ILogger _logger;
#endregion
#region Ctor
///
/// Ctor
///
///
///
///
///
///
public AuctionService(
AuctionDbContext ctx,
IProductService productService,
IWorkContext workContext,
IOrderProcessingService orderProcessingService,
IShoppingCartService shoppingCartService,
IStoreContext storeContext,
ILogger logger)
{
_ctx = ctx;
_productService = productService;
_workContext = workContext;
_orderProcessingService = orderProcessingService;
_shoppingCartService = shoppingCartService;
_storeContext = storeContext;
_paymentService = paymentService;
_logger = logger;
}
#endregion
#region Methods
public static decimal GetStepAmount(decimal currentPrice)
{
return currentPrice switch
{
>= 0 and < 100000 => 10000,
//100 000 - 1 000 000
>= 100000 and < 200000 => 10000,
>= 200000 and < 500000 => 20000,
>= 500000 and < 1000000 => 50000,
//1 000 000 - 10 000 000
>= 1000000 and < 2000000 => 100000,
>= 2000000 and < 5000000 => 200000,
>= 5000000 and < 10000000 => 500000,
//10 000 000 - 100 000 000
>= 10000000 and < 20000000 => 1000000,
>= 20000000 and < 50000000 => 2000000,
>= 50000000 and < 100000000 => 5000000,
//100 000 000 - ~
>= 100000000 and < 200000000 => 10000000,
_ => 20000000
};
//100 000 Ft – 200 000 Ft között 10 000 Ft-tal
//200 000 Ft – 500 000 Ft között 20 000 Ft-tal
//500 000 Ft – 1 000 000 Ft között 50 000 Ft-tal
//1 000 000 Ft – 2 000 000 Ft között 100 000 Ft-tal
//2 000 000 Ft – 5 000 000 Ft között 200 000 Ft-tal
//5 000 000 Ft – 10 000 000 Ft között 500 000 Ft-tal
//10 000 000 Ft – 20 000 000 Ft között 1 000 000 Ft-tal
//20 000 000 Ft – 50 000 000 Ft között 2 000 000 Ft-tal
//50 000 000 Ft – 100 000 000 Ft között 5 000 000 Ft-tal
//100 000 000 Ft – 200 000 000 Ft között 10 000 000 Ft-tal
//200 000 000 Ft fölött 20 000 000 Ft-tal
}
public static decimal GetNextBidPrice(decimal currentBidPrice) => GetNextBidPrice(currentBidPrice, GetStepAmount(currentBidPrice));
public static decimal GetNextBidPrice(decimal currentBidPrice, decimal stepAmount)
{
return currentBidPrice + stepAmount;
}
public async Task ResetProductToAuctionByProductId(int productId)
=> await ResetProductToAuctionAsync(await _ctx.ProductToAuctions.GetByProductId(productId).FirstOrDefaultAsync());
public Task ResetProductToAuctionByIdAsync(int productToAuctionId, decimal basePrice = 0)
=> ResetProductToAuctionAsync(_ctx.ProductToAuctions.GetById(productToAuctionId), basePrice);
public Task ResetProductToAuctionAsync(ProductToAuctionMapping productToAuction, decimal basePrice = 0)
=> _ctx.ResetProductToAuctionAsync(productToAuction, basePrice);
public Task GetLastAuctionBidByProductToAuctionIdAsync(int productToAuctionId)
=> _ctx.GetLastAuctionBidByProductToAuctionId(productToAuctionId);
public Task GetBidsCountByProductToAuctionIdAsync(int productToAuctionId)
=> _ctx.GetBidsCountByProductToAuctionIdAsync(productToAuctionId);
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
/// Page index
/// Page size
///
/// A task that represents the asynchronous operation
/// The task result contains the bids
///
public async Task> GetAllBidsAsync(int customerId = 0, int pageIndex = 0, int pageSize = int.MaxValue)
{
//TODO: megcsinálni! - J.
var rez = new List();
//var rez = await _shortTermCacheManager.GetAsync(async () => await _customerBidRepository.GetAllAsync(query =>
//{
// if (customerId > 0)
// query = query.Where(bid => bid.CustomerId == customerId || bid.CustomerId == 0);
// query = query.OrderBy(bid => bid.CreateDate).ThenBy(bid => bid.ProductId);
// return query;
//}), _pickupPointAllKey, customerId);
return new PagedList(rez, pageIndex, pageSize);
}
public async Task GetBidByIdAsync(int bidId)
{
return await _ctx.AuctionBids.GetByIdAsync(bidId);
}
public async Task InsertBidAsync(AuctionBid auctionBid)
{
//if (await ValidateAuctionBid(auctionBid))
{
await _ctx.AuctionBids.InsertAsync(auctionBid, false);
}
}
public async Task UpdateBidAsync(AuctionBid auctionBid)
{
//if (await ValidateAuctionBid(auctionBid))
{
await _ctx.AuctionBids.UpdateAsync(auctionBid, false);
}
}
///
/// Deletes a pickup point
///
/// Pickup point
/// A task that represents the asynchronous operation
public async Task DeleteBidAsync(AuctionBid pickupPoint)
{
await _ctx.AuctionBids.DeleteAsync(pickupPoint, false);
}
public async Task CreateOrderForWinnerAsync(ProductToAuctionMapping auctionItem)
{
if (auctionItem is not { AuctionStatus: AuctionStatus.Sold })
{
await _logger.InformationAsync($"AuctionService.CreateOrderForWinnerAsync(); (auctionItem is not {{ AuctionStatus: AuctionStatus.Sold }}); auctionItemId: {auctionItem?.Id}; status: {auctionItem?.AuctionStatus}");
return null;
}
try
{
var processPaymentRequest = new ProcessPaymentRequest
{
PaymentMethodSystemName = "Payments.CheckMoneyOrder",
CustomerId = auctionItem.WinnerCustomerId,
OrderTotal = auctionItem.CurrentPrice,
};
var currentCustomer = await _workContext.GetCurrentCustomerAsync();
var product = await _productService.GetProductByIdAsync(auctionItem.ProductId);
var currentStore = await _storeContext.GetCurrentStoreAsync();
processPaymentRequest.CustomValues.Add("ProductToAuctionMappingId", auctionItem.Id);
product.DisableBuyButton = false;
var cartResult = await _shoppingCartService.AddToCartAsync(currentCustomer, product, ShoppingCartType.ShoppingCart, currentStore.Id);
//TODO: valszeg a GenerateOrderGuidAsync-ot kell használni, de nemtom egy példában láttam... - J.
await _paymentService.GenerateOrderGuidAsync(processPaymentRequest);
var placeOrderResult = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
if (!placeOrderResult.Success) return null;
auctionItem.OrderId = placeOrderResult.PlacedOrder.Id;
auctionItem.OrderGuid = placeOrderResult.PlacedOrder.OrderGuid;
return placeOrderResult;
}
catch (Exception ex)
{
_logger.Error($"AuctionService.CreateOrderForWinnerAsync(); Exception; auctionItemId: {auctionItem.Id}", ex);
}
return null;
}
#region auctions
public async Task InsertAuctionAsync(Auction auction)
{
await _ctx.Auctions.InsertAsync(auction, false);
}
public async Task UpdateAuctionAsync(Auction auction)
{
await _ctx.Auctions.UpdateAsync(auction);
}
public async Task> GetAllAuctionsAsync()
{
return await _ctx.Auctions.GetAllAuctionsAsync();
}
public async Task> GetProductToAuctionsByAuctionIdAsync(int auctionId, bool onlyActiveItems)
{
return await _ctx.ProductToAuctions.GetProductToAuctionsByAuctionId(auctionId, onlyActiveItems).ToListAsync();
}
#endregion
#endregion
#region Dtos
public async Task GetAuctionDtoWithAuctionBids(int auctionId, bool activeProductOnly, int maxBidsCount = int.MaxValue)
{
var auctionDto = await GetAuctionDtoByIdAsync(auctionId, true, activeProductOnly);
if (auctionDto == null) return null;
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());
}
return auctionDto;
}
public async Task GetAuctionDtoByIdAsync(int auctionId, bool widthProducts, bool activeProductOnly)
{
var auction = await _ctx.Auctions.GetByIdAsync(auctionId);
if (auction == null) return null;
var auctionDto = new AuctionDto(auction);
if (widthProducts) auctionDto.ProductToAuctionDtos.AddRange((await GetProductToAuctionDtosByAuctionId(auctionId, activeProductOnly)));
return auctionDto;
}
public async Task> GetProductToAuctionDtosByAuctionId(int auctionId, bool activeProductOnly)
{
return (await GetProductToAuctionsByAuctionIdAsync(auctionId, activeProductOnly)).Select(x => new ProductToAuctionDto(x)).ToList();
}
public async Task GetAuctionDtoWithProductByIdAsync(int auctionId, int productId, bool activeProductOnly)
{
var auction = await _ctx.Auctions.GetByIdAsync(auctionId);
if (auction == null) return null;
var auctionDto = new AuctionDto(auction);
auctionDto.ProductToAuctionDtos.AddRange((await GetProductToAuctionByAuctionIdAndProductIdAsync(auctionId, productId, activeProductOnly)).Select(x => new ProductToAuctionDto(x)));
return auctionDto;
}
public async Task GetProductToAuctionDtoByIdAsync(int productToAuctionId)
{
var productToAuction = await _ctx.ProductToAuctions.GetByIdAsync(productToAuctionId);
return productToAuction == null ? null : new ProductToAuctionDto(productToAuction);
}
public async Task GetAuctionDtoByProductToAuctionIdAsync(int productToAuctionId, bool includeProductToAuctionDto)
{
var productTouctionDto = await GetProductToAuctionDtoByIdAsync(productToAuctionId);
if (productTouctionDto == null) return null;
var auctionDto = await GetAuctionDtoByIdAsync(productTouctionDto.AuctionId, false, false);
if (includeProductToAuctionDto) auctionDto.ProductToAuctionDtos.Add(productTouctionDto);
return auctionDto;
}
public async Task> GetProductToAuctionDtosByProductIdAsync(int productId)
{
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)
=> _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)
{
var auction = await GetAuctionDtoByIdAsync(auctionId, false, false);
if (auction == null)
return null;
var existedProductToAuction = (await GetProductToAuctionByAuctionIdAndProductIdAsync(auctionId, productId, false)).FirstOrDefault();
if (existedProductToAuction != null) return existedProductToAuction;
var mapping = new ProductToAuctionMapping
{
ProductId = productId,
StartingPrice = startingPrice,
CurrentPrice = bidPrice,
ProductAmount = 1,
AuctionStatus = AuctionStatus.None,
AuctionId = auctionId
};
try
{
await _ctx.ProductToAuctions.InsertAsync(mapping);
}
catch (Exception ex)
{
await _logger.InformationAsync(ex.ToString());
}
return mapping;
}
public async Task GetProductToAuctionMappingByIdAsync(int productToAuctionMappingId)
{
return await _ctx.ProductToAuctions.GetByIdAsync(productToAuctionMappingId);
}
public async Task UpdateProductToAuctionMappingAsync(ProductToAuctionMapping productToAuctionMapping)
{
await _ctx.ProductToAuctions.UpdateAsync(productToAuctionMapping);
}
#endregion Dtos
}