Skip to content

Commit

Permalink
fix: actualize config line item price
Browse files Browse the repository at this point in the history
  • Loading branch information
ksavosteev committed Nov 19, 2024
1 parent 86a939e commit 42c8699
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 45 deletions.
54 changes: 29 additions & 25 deletions src/VirtoCommerce.XCart.Core/ConfiguredLineItemContainer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using VirtoCommerce.CartModule.Core.Model;
using VirtoCommerce.CoreModule.Core.Currency;
using VirtoCommerce.CustomerModule.Core.Model;
Expand Down Expand Up @@ -32,22 +31,23 @@ public class ConfiguredLineItemContainer : ICartProductContainer, ICloneable
public CartProduct ConfigurableProduct { get; set; }
public IList<LineItem> Items { get; set; } = new List<LineItem>();

private readonly IMapper _mapper;

public ConfiguredLineItemContainer(IMapper mapper)
{
_mapper = mapper;
}

public LineItem CreateItem(CartProduct cartProduct, int quantity)
public LineItem AddItem(CartProduct cartProduct, int quantity)
{
var lineItem = _mapper.Map<LineItem>(cartProduct);
var lineItem = AbstractTypeFactory<LineItem>.TryCreateInstance();
lineItem.ProductId = cartProduct.Id;
lineItem.Name = cartProduct.Product.Name;
lineItem.Sku = cartProduct.Product.Code;
lineItem.ImageUrl = cartProduct.Product.ImgSrc;
lineItem.CatalogId = cartProduct.Product.CatalogId;
lineItem.CategoryId = cartProduct.Product.CategoryId;

lineItem.Quantity = quantity;

// calculate prices and only static rewards
if (cartProduct.Price != null)
{
lineItem.Currency = cartProduct.Price.Currency.Code;

var tierPrice = cartProduct.Price.GetTierPrice(quantity);
if (tierPrice.Price.Amount > 0)
{
Expand All @@ -60,6 +60,8 @@ public LineItem CreateItem(CartProduct cartProduct, int quantity)
lineItem.ExtendedPrice = lineItem.PlacedPrice * lineItem.Quantity;
}

Items.Add(lineItem);

return lineItem;
}

Expand Down Expand Up @@ -89,21 +91,6 @@ public LineItem CreateConfiguredLineItem()
lineItem.FulfillmentCenterName = ConfigurableProduct.Inventory?.FulfillmentCenterName;
lineItem.VendorId = ConfigurableProduct.Product.Vendor;

// prices
lineItem.Currency = Currency.Code;

if (ConfigurableProduct.Price == null)
{
ConfigurableProduct.Price = new Xapi.Core.Models.ProductPrice(Currency);
}

lineItem.ListPrice = Items.Sum(x => x.ListPrice) + ConfigurableProduct.Price.ListPrice.Amount;
lineItem.SalePrice = Items.Sum(x => x.SalePrice) + ConfigurableProduct.Price.SalePrice.Amount;

lineItem.DiscountAmount = Math.Max(0, lineItem.ListPrice - lineItem.SalePrice);
lineItem.PlacedPrice = lineItem.ListPrice - lineItem.DiscountAmount;
lineItem.ExtendedPrice = lineItem.PlacedPrice * lineItem.Quantity;

// create sub items
lineItem.ConfigurationItems = Items
.Select(x =>
Expand All @@ -122,9 +109,26 @@ public LineItem CreateConfiguredLineItem()
})
.ToList();

// prices
lineItem.Currency = Currency.Code;

UpdatePrice(lineItem);

return lineItem;
}

public void UpdatePrice(LineItem lineItem)
{
var configurableProductPrice = ConfigurableProduct.Price ?? new Xapi.Core.Models.ProductPrice(Currency);

lineItem.ListPrice = Items.Sum(x => x.ListPrice) + configurableProductPrice.ListPrice.Amount;
lineItem.SalePrice = Items.Sum(x => x.SalePrice) + configurableProductPrice.SalePrice.Amount;

lineItem.DiscountAmount = Math.Max(0, lineItem.ListPrice - lineItem.SalePrice);
lineItem.PlacedPrice = lineItem.ListPrice - lineItem.DiscountAmount;
lineItem.ExtendedPrice = lineItem.PlacedPrice * lineItem.Quantity;
}

public object Clone()
{
return MemberwiseClone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,17 @@ namespace VirtoCommerce.XCart.Data.Commands;

public class CreateConfiguredLineItemHandler : IRequestHandler<CreateConfiguredLineItemCommand, ExpConfigurationLineItem>
{
private readonly Func<ConfiguredLineItemContainer> _configurableLineItemAggregateFactory;
private readonly ICurrencyService _currencyService;
private readonly IMemberResolver _memberResolver;
private readonly IStoreService _storeService;
private readonly ICartProductService2 _cartProductService;

public CreateConfiguredLineItemHandler(
Func<ConfiguredLineItemContainer> configurableLineItemContainerFactory,
ICurrencyService currencyService,
IMemberResolver memberResolver,
IStoreService storeService,
ICartProductService2 cartProductService)
{
_configurableLineItemAggregateFactory = configurableLineItemContainerFactory;
_currencyService = currencyService;
_memberResolver = memberResolver;
_storeService = storeService;
Expand Down Expand Up @@ -65,8 +62,7 @@ public async Task<ExpConfigurationLineItem> Handle(CreateConfiguredLineItemComma
throw new OperationCanceledException($"Product with id {productOption.ProductId} not found");
}

var item = container.CreateItem(selectedProduct, productOption.Quantity);
container.Items.Add(item);
_ = container.AddItem(selectedProduct, productOption.Quantity);
}

var configuredItem = container.CreateConfiguredLineItem();
Expand All @@ -78,7 +74,6 @@ public async Task<ExpConfigurationLineItem> Handle(CreateConfiguredLineItemComma
};
}

// todo: move to the separate service
private async Task<ConfiguredLineItemContainer> CreateContainer(CreateConfiguredLineItemCommand request)
{
var storeLoadTask = _storeService.GetByIdAsync(request.StoreId);
Expand All @@ -99,7 +94,7 @@ private async Task<ConfiguredLineItemContainer> CreateContainer(CreateConfigured

var member = await _memberResolver.ResolveMemberByIdAsync(request.UserId);

var container = _configurableLineItemAggregateFactory();
var container = AbstractTypeFactory<ConfiguredLineItemContainer>.TryCreateInstance();

container.Store = store;
container.Member = member;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ public static IServiceCollection AddXCart(this IServiceCollection services, IGra
services.AddTransient<Func<CartAggregate>>(provider => () => provider.CreateScope().ServiceProvider.GetRequiredService<CartAggregate>());

services.AddTransient<ICartProductService2, CartProductService>();
services.AddTransient<ConfiguredLineItemContainer>();
services.AddTransient<Func<ConfiguredLineItemContainer>>(provider => () => provider.CreateScope().ServiceProvider.GetRequiredService<ConfiguredLineItemContainer>());

services.AddPipeline<SearchProductResponse>(builder =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,19 @@ namespace VirtoCommerce.XCatalog.Data.Queries;

public class GetProductConfigurationQueryHandler : IQueryHandler<GetProductConfigurationQuery, ProductConfigurationQueryResponse>
{
private readonly Func<ConfiguredLineItemContainer> _configurableLineItemAggregateFactory;
private readonly IConfigurableProductService _configurableProductService;
private readonly ICurrencyService _currencyService;
private readonly IMemberResolver _memberResolver;
private readonly IStoreService _storeService;
private readonly ICartProductService2 _cartProductService;
//private readonly IMediator _mediator;

private const string _productsFieldName = $"{nameof(ProductConfigurationQueryResponse.ConfigurationSections)}.{nameof(ExpProductConfigurationSection.Options)}";

public GetProductConfigurationQueryHandler(
Func<ConfiguredLineItemContainer> configurableLineItemContainerFactory,
IConfigurableProductService configurableProductService,
ICurrencyService currencyService,
IMemberResolver memberResolver,
IStoreService storeService,
ICartProductService2 cartProductService)
{
_configurableLineItemAggregateFactory = configurableLineItemContainerFactory;
_configurableProductService = configurableProductService;
_currencyService = currencyService;
_memberResolver = memberResolver;
Expand Down Expand Up @@ -72,7 +66,7 @@ public async Task<ProductConfigurationQueryResponse> Handle(GetProductConfigurat
{
if (productByIds.TryGetValue(option.ProductId, out var cartProduct))
{
var item = containter.CreateItem(cartProduct, option.Quantity);
var item = containter.AddItem(cartProduct, option.Quantity);
item.Id = option.Id;

var expConfigurationLineItem = new ExpConfigurationLineItem
Expand All @@ -90,7 +84,6 @@ public async Task<ProductConfigurationQueryResponse> Handle(GetProductConfigurat
return result;
}

// todo: move to the separate service
private async Task<ConfiguredLineItemContainer> CreateContainer(GetProductConfigurationQuery request)
{
var storeLoadTask = _storeService.GetByIdAsync(request.StoreId);
Expand All @@ -111,7 +104,7 @@ private async Task<ConfiguredLineItemContainer> CreateContainer(GetProductConfig

var member = await _memberResolver.ResolveMemberByIdAsync(request.UserId);

var container = _configurableLineItemAggregateFactory();
var container = AbstractTypeFactory<ConfiguredLineItemContainer>.TryCreateInstance();

container.Store = store;
container.Member = member;
Expand Down
47 changes: 45 additions & 2 deletions src/VirtoCommerce.XCart.Data/Services/CartAggregateRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,57 @@ private async Task<CartAggregate> InnerGetCartAggregateFromCartNoCacheAsync(Shop
aggregate.ValidationWarnings.AddRange(result.Errors);
}

// update price
aggregate.SetLineItemTierPrice(cartProduct.Price, lineItem.Quantity, lineItem);
// update price for non-configured line items immediately
if (!lineItem.IsConfigured)
{
aggregate.SetLineItemTierPrice(cartProduct.Price, lineItem.Quantity, lineItem);
}
}

await UpdateConfiguredLineItemPrice(aggregate);

await aggregate.RecalculateAsync();

return aggregate;
}
}

private async Task UpdateConfiguredLineItemPrice(CartAggregate aggregate)
{
var configurationLineItems = aggregate.LineItems.Where(x => x.IsConfigured).ToArray();

var configProductsIds = configurationLineItems
.SelectMany(x => x.ConfigurationItems.Select(x => x.ProductId))
.Distinct()
.ToArray();

if (configProductsIds.Length == 0)
{
return;
}

var configProducts = await _cartProductsService.GetCartProductsByIdsAsync(aggregate, configProductsIds.ToArray());

foreach (var configurationLineItem in configurationLineItems)
{
var contaner = AbstractTypeFactory<ConfiguredLineItemContainer>.TryCreateInstance();

if (aggregate.CartProducts.TryGetValue(configurationLineItem.ProductId, out var configurableProduct))
{
contaner.ConfigurableProduct = configurableProduct;
}

foreach (var configurationItem in configurationLineItem.ConfigurationItems)
{
var product = configProducts.FirstOrDefault(x => x.Product.Id == configurationItem.ProductId);
if (product != null)
{
contaner.AddItem(product, configurationItem.Quantity);
}
}

contaner.UpdatePrice(configurationLineItem);
}
}
}
}

0 comments on commit 42c8699

Please sign in to comment.