Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VCST-2092: add create configuration command #14

Merged
merged 32 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b6870be
feat: add create configuration command (mock)
ksavosteev Oct 29, 2024
ec7e9bb
feat: add configuration to InputAddItemType
ksavosteev Nov 1, 2024
b027537
feat: add configured line item
ksavosteev Nov 5, 2024
7d0d9c8
feat: update dependency
ksavosteev Nov 5, 2024
0f4e210
fix: sonar
ksavosteev Nov 5, 2024
ef238eb
feat: remove configurable product input
ksavosteev Nov 6, 2024
1d68fde
feat: fix add configured line items
ksavosteev Nov 7, 2024
80e2567
fix: temp fix for null discounts and taxdetails in line item
ksavosteev Nov 7, 2024
f74756f
Update CreateConfiguredLineItemHandler.cs
ksavosteev Nov 13, 2024
628eb99
fix
ksavosteev Nov 13, 2024
60068de
Merge branch 'feat/VCST-2092' of https://github.com/VirtoCommerce/vc-…
ksavosteev Nov 13, 2024
faf66bf
Merge branch 'dev' into feat/VCST-2092
asvishnyakov Nov 13, 2024
95f857e
feat: refactor
ksavosteev Nov 15, 2024
d13421c
Merge branch 'feat/VCST-2092' of https://github.com/VirtoCommerce/vc-…
ksavosteev Nov 15, 2024
8d6505f
fix: update dependenies
ksavosteev Nov 15, 2024
14f53e3
Merge branch 'dev' into feat/VCST-2092
ksavosteev Nov 15, 2024
86a939e
fix: non nullable ID in ConfigurationSectionType
ksavosteev Nov 18, 2024
42c8699
fix: actualize config line item price
ksavosteev Nov 19, 2024
c0a1c34
fix NRE
ksavosteev Nov 20, 2024
46b67bc
fix: fix config line item total
ksavosteev Nov 20, 2024
d684aa5
fix: sonar, refactor
ksavosteev Nov 20, 2024
2daf0f7
fix: sonar
ksavosteev Nov 20, 2024
bb8ec21
Merge branch 'dev' into feat/VCST-2092
ksavosteev Nov 21, 2024
0efe4c5
refactor
ksavosteev Nov 21, 2024
55540a6
Merge branch 'feat/VCST-2092' of https://github.com/VirtoCommerce/vc-…
ksavosteev Nov 21, 2024
7289174
fix build
ksavosteev Nov 21, 2024
054a3da
feat: refactor
ksavosteev Nov 21, 2024
6fc4a20
fix: sonar
ksavosteev Nov 21, 2024
bd55e7e
fix: undo changes
ksavosteev Nov 21, 2024
a2fad2c
fix: sonar
ksavosteev Nov 25, 2024
d63a208
fix: refactor
ksavosteev Nov 25, 2024
c3f7951
feat: update dependency
ksavosteev Nov 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion src/VirtoCommerce.XCart.Core/CartAggregate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,42 @@ public virtual Task<CartAggregate> UpdateCartComment(string comment)
return Task.FromResult(this);
}

/// <summary>
/// Always add a new line item for a configured item.
/// </summary>
/// <param name="newCartItem"></param>
/// <param name="newConfiguredItem"></param>
/// <returns></returns>
public virtual async Task<CartAggregate> AddConfiguredItemAsync(NewCartItem newCartItem, LineItem newConfiguredItem)
{
EnsureCartExists();

ArgumentNullException.ThrowIfNull(newCartItem);
ksavosteev marked this conversation as resolved.
Show resolved Hide resolved
ArgumentNullException.ThrowIfNull(newConfiguredItem);

if (newCartItem.CartProduct != null)
{
CartProducts[newCartItem.CartProduct.Id] = newCartItem.CartProduct;

newConfiguredItem.Id = null;
newConfiguredItem.SelectedForCheckout = IsSelectedForCheckout;
newConfiguredItem.Quantity = newCartItem.Quantity;
newConfiguredItem.Note = newCartItem.Comment;

Cart.Items.Add(newConfiguredItem);

if (newCartItem.DynamicProperties != null)
{
await UpdateCartItemDynamicProperties(newConfiguredItem, newCartItem.DynamicProperties);
}

await SetItemFulfillmentCenterAsync(newConfiguredItem, newCartItem.CartProduct);
await UpdateVendor(newConfiguredItem, newCartItem.CartProduct);
}

return this;
}

public virtual async Task<CartAggregate> AddItemAsync(NewCartItem newCartItem)
{
EnsureCartExists();
Expand Down Expand Up @@ -956,7 +992,7 @@ protected virtual Task<CartAggregate> InnerChangeItemQuantityAsync(LineItem line
{
ArgumentNullException.ThrowIfNull(lineItem);

if (!lineItem.IsReadOnly && product != null)
if (!lineItem.IsReadOnly && product?.Price != null)
{
var tierPrice = product.Price.GetTierPrice(quantity);
if (CheckPricePolicy(tierPrice))
Expand Down
6 changes: 6 additions & 0 deletions src/VirtoCommerce.XCart.Core/Commands/AddCartItemCommand.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using VirtoCommerce.Xapi.Core.Models;
using VirtoCommerce.XCart.Core.Commands.BaseCommands;
using VirtoCommerce.XCart.Core.Models;

namespace VirtoCommerce.XCart.Core.Commands
{
Expand All @@ -23,5 +24,10 @@ public class AddCartItemCommand : CartCommand
/// Dynamic properties
/// </summary>
public IList<DynamicPropertyValue> DynamicProperties { get; set; }

/// <summary>
/// Configurable product sections
/// </summary>
public IList<ProductConfigurationSection> ConfigurationSections { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using VirtoCommerce.Xapi.Core.Infrastructure;
using VirtoCommerce.XCart.Core.Models;

namespace VirtoCommerce.XCart.Core.Commands;

public class CreateConfiguredLineItemCommand : ICommand<ExpConfigurationLineItem>, ICartProductContainerRequest
{
public string StoreId { get; set; }

public string UserId { get; set; }

public string OrganizationId { get; set; }

public string CurrencyCode { get; set; }

public string CultureName { get; set; }

public string ConfigurableProductId { get; set; }

public IList<ProductConfigurationSection> ConfigurationSections { get; set; } = [];
}
148 changes: 148 additions & 0 deletions src/VirtoCommerce.XCart.Core/ConfiguredLineItemContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Linq;
using VirtoCommerce.CartModule.Core.Model;
using VirtoCommerce.CoreModule.Core.Currency;
using VirtoCommerce.CustomerModule.Core.Model;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.StoreModule.Core.Model;
using VirtoCommerce.XCart.Core.Models;

namespace VirtoCommerce.XCart.Core
{
public class ConfiguredLineItemContainer : ICloneable
{
public Currency Currency { get; set; }
public Store Store { get; set; }
public Member Member { get; set; }
public string CultureName { get; set; }
public string UserId { get; set; }
public IList<string> ProductsIncludeFields { get; set; }

public CartProduct ConfigurableProduct { get; set; }
public IList<LineItem> Items { get; set; } = new List<LineItem>();

public LineItem AddItem(CartProduct cartProduct, int quantity)
{
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)
{
lineItem.SalePrice = tierPrice.ActualPrice.Amount;
lineItem.ListPrice = tierPrice.Price.Amount;
}

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

Items.Add(lineItem);

return lineItem;
}

public ExpConfigurationLineItem CreateConfiguredLineItem()
{
var lineItem = AbstractTypeFactory<LineItem>.TryCreateInstance();

lineItem.IsConfigured = true;
lineItem.Quantity = 1;

lineItem.Discounts = [];
lineItem.TaxDetails = [];

lineItem.ProductId = ConfigurableProduct.Product.Id;
lineItem.Sku = $"Configuration-{ConfigurableProduct.Product.Code}";

lineItem.CatalogId = ConfigurableProduct.Product.CatalogId;
lineItem.CategoryId = ConfigurableProduct.Product.CategoryId;

lineItem.Name = ConfigurableProduct.Product.Name;
lineItem.ImageUrl = ConfigurableProduct.Product.ImgSrc;
lineItem.ProductOuterId = ConfigurableProduct.Product.OuterId;
lineItem.ProductType = ConfigurableProduct.Product.ProductType;
lineItem.TaxType = ConfigurableProduct.Product.TaxType;

lineItem.FulfillmentCenterId = ConfigurableProduct.Inventory?.FulfillmentCenterId;
lineItem.FulfillmentCenterName = ConfigurableProduct.Inventory?.FulfillmentCenterName;
lineItem.VendorId = ConfigurableProduct.Product.Vendor;

// create sub items
lineItem.ConfigurationItems = Items
.Select(x =>
{
var subItem = AbstractTypeFactory<ConfigurationItem>.TryCreateInstance();

subItem.ProductId = x.ProductId;
subItem.Name = x.Name;
subItem.Sku = x.Sku;
subItem.ImageUrl = x.ImageUrl;
subItem.Quantity = x.Quantity;
subItem.CatalogId = x.CatalogId;
subItem.CategoryId = x.CategoryId;

return subItem;
})
.ToList();

// prices
lineItem.Currency = Currency.Code;

UpdatePrice(lineItem);

return new ExpConfigurationLineItem
{
Item = lineItem,
Currency = Currency,
CultureName = CultureName,
UserId = UserId,
StoreId = Store.Id,
};
}

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

lineItem.ListPrice = Items.Sum(x => x.ListPrice * x.Quantity) + configurableProductPrice.ListPrice.Amount;
lineItem.SalePrice = Items.Sum(x => x.SalePrice * x.Quantity) + 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 CartProductsRequest GetCartProductsRequest()
{
var request = AbstractTypeFactory<CartProductsRequest>.TryCreateInstance();

request.Store = Store;
request.Currency = Currency;
request.CultureName = CultureName;
request.Member = Member;
request.UserId = UserId;

return request;
}

public object Clone()
{
return MemberwiseClone();
}
}
}
15 changes: 15 additions & 0 deletions src/VirtoCommerce.XCart.Core/ExpConfigurationLineItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using VirtoCommerce.CartModule.Core.Model;
using VirtoCommerce.CoreModule.Core.Currency;

namespace VirtoCommerce.XCart.Core
{
public class ExpConfigurationLineItem
{
public string StoreId { get; set; }
public string UserId { get; set; }
public string CultureName { get; set; }

public LineItem Item { get; set; }
public Currency Currency { get; set; }
}
}
21 changes: 21 additions & 0 deletions src/VirtoCommerce.XCart.Core/Models/CartProductsRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Generic;
using VirtoCommerce.CoreModule.Core.Currency;
using VirtoCommerce.CustomerModule.Core.Model;
using VirtoCommerce.StoreModule.Core.Model;

namespace VirtoCommerce.XCart.Core.Models;

public class CartProductsRequest
{
public Store Store { get; set; }
public string CultureName { get; set; }
public Currency Currency { get; set; }
public Member Member { get; set; }
public string UserId { get; set; }

public IList<string> ProductIds { get; set; }
public IList<string> ProductsIncludeFields { get; set; }

public bool LoadPrice { get; set; } = true;
public bool LoadInventory { get; set; } = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace VirtoCommerce.XCart.Core.Models;

public class ConfigurableProductOption
{
public string ProductId { get; set; }

public int Quantity { get; set; } = 1;
}
19 changes: 19 additions & 0 deletions src/VirtoCommerce.XCart.Core/Models/ExpConfigurationSection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Collections.Generic;

namespace VirtoCommerce.XCart.Core.Models;

public class ExpProductConfigurationSection
{
public string Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Description { get; set; }
public bool IsRequired { get; set; }

public IList<ExpConfigurationLineItem> Options { get; set; } = new List<ExpConfigurationLineItem>();
}

public class ProductConfigurationQueryResponse
{
public IList<ExpProductConfigurationSection> ConfigurationSections { get; set; } = new List<ExpProductConfigurationSection>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace VirtoCommerce.XCart.Core.Models;

public interface ICartProductContainerRequest
{
string StoreId { get; set; }
string UserId { get; set; }
string OrganizationId { get; set; }
string CurrencyCode { get; set; }
string CultureName { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace VirtoCommerce.XCart.Core.Models;

public class ProductConfigurationSection
{
public string SectionId { get; set; }

public ConfigurableProductOption Value { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using GraphQL;
using GraphQL.Types;
using VirtoCommerce.StoreModule.Core.Model;
using VirtoCommerce.Xapi.Core.BaseQueries;
using VirtoCommerce.Xapi.Core.Extensions;
using VirtoCommerce.XCart.Core.Models;

namespace VirtoCommerce.XCart.Core.Queries;

public class GetProductConfigurationQuery : Query<ProductConfigurationQueryResponse>, ICartProductContainerRequest
{
public string ConfigurableProductId { get; set; }

public string StoreId { get; set; }

public string UserId { get; set; }

public string OrganizationId { get; set; }

public string CurrencyCode { get; set; }

public string CultureName { get; set; }

public Store Store { get; set; }

public IList<string> IncludeFields { get; set; } = Array.Empty<string>();

public override IEnumerable<QueryArgument> GetArguments()
{
yield return Argument<NonNullGraphType<StringGraphType>>(nameof(ConfigurableProductId));

yield return Argument<NonNullGraphType<StringGraphType>>(nameof(StoreId), description: "Store Id");
yield return Argument<StringGraphType>(nameof(UserId), description: "User Id");
yield return Argument<StringGraphType>(nameof(CultureName), description: "Currency code (\"USD\")");
yield return Argument<StringGraphType>(nameof(CurrencyCode), description: "Culture name (\"en-US\")");
}

public override void Map(IResolveFieldContext context)
{
ConfigurableProductId = context.GetArgument<string>(nameof(ConfigurableProductId));

StoreId = context.GetArgument<string>(nameof(StoreId));
UserId = context.GetArgument<string>(nameof(UserId)) ?? context.GetCurrentUserId();
OrganizationId = context.GetCurrentOrganizationId();
CultureName = context.GetArgument<string>(nameof(CultureName));
CurrencyCode = context.GetArgument<string>(nameof(CurrencyCode));
}
}
14 changes: 14 additions & 0 deletions src/VirtoCommerce.XCart.Core/Schemas/CartConfigurationItemType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using VirtoCommerce.CartModule.Core.Model;
using VirtoCommerce.Xapi.Core.Schemas;

namespace VirtoCommerce.XCart.Core.Schemas
{
public class CartConfigurationItemType : ExtendableGraphType<ConfigurationItem>
{
public CartConfigurationItemType()
{
Field(x => x.Id, nullable: false).Description("Configuration item ID");
Field(x => x.Name, nullable: true).Description("Configuration item name");
}
}
}
Loading
Loading