Skip to content
This repository has been archived by the owner on Jun 13, 2023. It is now read-only.

Commit

Permalink
VDS-690: Implement ability of bulk variations adding to cart. API cha…
Browse files Browse the repository at this point in the history
…nges (#55)

* Regenerate Order and Cart modules API clients

* Revert GetInvoicePdfWithHttpMessagesAsync method behavior customly

* Extend configured group models with Name and ImageUrl

* Revert Revert GetInvoicePdf continue

* Remove second constructor

* VDS-690: Add API to calculate product prices

* Implement the bulk items adding to cart. Not only for the configured product.

* Take into account PR notes

* Add total without tax

* Fix pdf generation.

Co-authored-by: trueboroda <superiorboroda@gmail.com>
  • Loading branch information
asvishnyakov and trueboroda committed Feb 2, 2021
1 parent 07895b2 commit 795f154
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 20 deletions.
20 changes: 20 additions & 0 deletions VirtoCommerce.Storefront.Model/Catalog/ProductTotal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using VirtoCommerce.Storefront.Model.Common;

namespace VirtoCommerce.Storefront.Model.Catalog
{
public class ProductTotal
{
public Money Total { get; set; }
public Money TotalWithTax { get; set; }

public Money SubTotal { get; set; }

public Money SubTotalWithTax { get; set; }

public Money DiscountTotal { get; set; }

public Money DiscountTotalWithTax { get; set; }

public Money TaxTotal { get; set; }
}
}
7 changes: 3 additions & 4 deletions VirtoCommerce.Storefront/AutoRestClients/OrdersModuleApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3574,10 +3574,9 @@ public static Stream GetInvoicePdf(this IOrderModule operations, string orderNum
/// </param>
public static async Task<Stream> GetInvoicePdfAsync(this IOrderModule operations, string orderNumber, CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.GetInvoicePdfWithHttpMessagesAsync(orderNumber, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
var _result = await operations.GetInvoicePdfWithHttpMessagesAsync(orderNumber, null, cancellationToken).ConfigureAwait(false);
_result.Request.Dispose();
return _result.Body;
}

/// <param name='operations'>
Expand Down
36 changes: 21 additions & 15 deletions VirtoCommerce.Storefront/Controllers/Api/ApiCartDemoController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using VirtoCommerce.Storefront.Infrastructure;
using VirtoCommerce.Storefront.Model;
using VirtoCommerce.Storefront.Model.Cart;
using VirtoCommerce.Storefront.Model.Cart.Demo;
using VirtoCommerce.Storefront.Model.Cart.Services;
using VirtoCommerce.Storefront.Model.Cart.Validators;
using VirtoCommerce.Storefront.Model.Common;
Expand Down Expand Up @@ -49,30 +50,35 @@ public async Task<ActionResult<AddItemsToCartResult>> AddItemsToCart([FromBody]
var cartBuilder = await LoadOrCreateCartAsync();
var cart = _cartBuilder.Cart;
var currency = WorkContext.CurrentCurrency;

var firstItem = items.First();

var configuredProductId = firstItem.ConfiguredProductId;
ConfiguredGroup configuredGroup = null;

var configuredGroup = cart.ConfiguredGroups?.FirstOrDefault(x => (x.ProductId == configuredProductId)
// case with the configured product adding
if (configuredProductId != null)
{
configuredGroup = cart.ConfiguredGroups?.FirstOrDefault(x => (x.ProductId == configuredProductId)
&& x.Items.OrderBy(x => x.ProductId).Select(x => x.ProductId).SequenceEqual(items.OrderBy(i => i.ProductId).Select(i => i.ProductId).ToArray())
);

if (configuredGroup == null)
{
var configuredProduct = (await _catalogService.GetProductsAsync(new string[] { configuredProductId }, Model.Catalog.ItemResponseGroup.ItemSmall)).FirstOrDefault();
configuredGroup = new Model.Cart.Demo.ConfiguredGroup(firstItem.Quantity, currency, configuredProductId)
if (configuredGroup == null)
{
Name = configuredProduct?.Name ?? "",
ImageUrl = configuredProduct?.PrimaryImage?.Url
};
cart.ConfiguredGroups.Add(configuredGroup);
}
else
{
configuredGroup.Quantity += Math.Max(1, firstItem.Quantity);
var configuredProduct = (await _catalogService.GetProductsAsync(new string[] { configuredProductId }, Model.Catalog.ItemResponseGroup.ItemSmall)).FirstOrDefault();
configuredGroup = new Model.Cart.Demo.ConfiguredGroup(firstItem.Quantity, currency, configuredProductId)
{
Name = configuredProduct?.Name ?? string.Empty,
ImageUrl = configuredProduct?.PrimaryImage?.Url
};
cart.ConfiguredGroups.Add(configuredGroup);
}
else
{
configuredGroup.Quantity += Math.Max(1, firstItem.Quantity);
}
}

foreach (var item in items)
{
item.ConfiguredGroupId = configuredGroup?.Id;
Expand Down
50 changes: 49 additions & 1 deletion VirtoCommerce.Storefront/Controllers/Api/ApiPricingController.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using VirtoCommerce.Storefront.Infrastructure;
using VirtoCommerce.Storefront.Model;
using VirtoCommerce.Storefront.Model.Cart;
using VirtoCommerce.Storefront.Model.Catalog;
using VirtoCommerce.Storefront.Model.Common;
using VirtoCommerce.Storefront.Model.Marketing.Services;
using VirtoCommerce.Storefront.Model.Pricing.Services;
using VirtoCommerce.Storefront.Model.Services;

namespace VirtoCommerce.Storefront.Controllers.Api
{
[StorefrontApiRoute("pricing")]
[ResponseCache(CacheProfileName = "None")]
public class ApiPricingController : StorefrontControllerBase
{
private readonly IWorkContextAccessor _workContextAccessor;
private readonly ICatalogService _catalogService;
private readonly IPricingService _pricingService;
private readonly IPromotionEvaluator _promotionEvaluator;

public ApiPricingController(IWorkContextAccessor workContextAccessor, IStorefrontUrlBuilder urlBuilder, IPromotionEvaluator promotionEvaluator, IPricingService pricingService)
public ApiPricingController(IWorkContextAccessor workContextAccessor, IStorefrontUrlBuilder urlBuilder,
ICatalogService catalogService, IPromotionEvaluator promotionEvaluator, IPricingService pricingService)
: base(workContextAccessor, urlBuilder)
{
_workContextAccessor = workContextAccessor;
_catalogService = catalogService;
_pricingService = pricingService;
_promotionEvaluator = promotionEvaluator;
}
Expand All @@ -40,5 +48,45 @@ public async Task<ActionResult<ProductPrice[]>> GetActualProductPrices([FromBody
}
return Ok();
}

// POST: storefrontapi/pricing/total
[HttpPost("total")]
public async Task<ActionResult<ProductPrice>> GetProductsTotal([FromBody] AddCartItem[] items)
{
// Based on https://github.com/VirtoCommerce/vc-module-cart/blob/05dac9453f375f015bbea57e3f95f4c87a62ec74/src/VirtoCommerce.CartModule.Data/Services/DefaultShoppingCartTotalsCalculator.cs#L57-L68
if (items != null && items.Any())
{
var products = await _catalogService.GetProductsAsync(items.Select(x => x.ProductId).ToArray(), ItemResponseGroup.ItemWithPrices);
if (products != null && products.Any())
{
var productsById = products.ToDictionary(x => x.Id, x => x);
foreach (var item in items)
{
item.Product = productsById[item.ProductId];
}

var currency = _workContextAccessor.WorkContext.CurrentCurrency;

// Original price without rounding stored in InternalAmount
var subTotal = items.Sum(x => x.Product.Price.ListPrice.InternalAmount * x.Quantity);
var subTotalWithTax = items.Sum(x => x.Product.Price.ListPriceWithTax.InternalAmount * x.Quantity);
var discountTotal = items.Sum(x => x.Product.Price.DiscountAmount.InternalAmount);
var discountTotalWithTax = items.Sum(x => x.Product.Price.DiscountAmountWithTax.InternalAmount);
var taxTotal = items.Sum(x => x.Product.TaxTotal.InternalAmount);
var productTotal = new ProductTotal
{
SubTotal = new Money(Math.Round(subTotal, 2, MidpointRounding.AwayFromZero), currency),
SubTotalWithTax = new Money(Math.Round(subTotalWithTax, 2, MidpointRounding.AwayFromZero), currency),
DiscountTotal = new Money(Math.Round(discountTotal, 2, MidpointRounding.AwayFromZero), currency),
DiscountTotalWithTax = new Money(Math.Round(discountTotalWithTax, 2, MidpointRounding.AwayFromZero), currency),
TaxTotal = new Money(Math.Round(taxTotal, 2, MidpointRounding.AwayFromZero), currency)
};
productTotal.Total = new Money(productTotal.SubTotal.Amount - productTotal.DiscountTotal.Amount, currency);
productTotal.TotalWithTax = new Money(productTotal.Total.Amount + productTotal.TaxTotal.Amount, currency);
return Ok(productTotal);
}
}
return Ok();
}
}
}

0 comments on commit 795f154

Please sign in to comment.