From 878b4a02b051104fb36dcd2252d9b2c6dbd6e157 Mon Sep 17 00:00:00 2001 From: Andrey Kozlov Date: Mon, 20 Apr 2020 20:57:04 +0500 Subject: [PATCH 1/2] VP-2011: Use available inventory if nothing in default ffc If item do not have record for inventory in default ffc, other available inventories could be used for inventory checking; --- VirtoCommerce.Storefront/Domain/Inventory/InventoryService.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/VirtoCommerce.Storefront/Domain/Inventory/InventoryService.cs b/VirtoCommerce.Storefront/Domain/Inventory/InventoryService.cs index 3e4d64fa9..c08e52263 100644 --- a/VirtoCommerce.Storefront/Domain/Inventory/InventoryService.cs +++ b/VirtoCommerce.Storefront/Domain/Inventory/InventoryService.cs @@ -51,9 +51,11 @@ public virtual async Task EvaluateProductInventoriesAsync(IEnumerable p //TODO: Change these conditions to DDD specification item.InventoryAll = inventories.Where(x => x.ProductId == item.Id).Select(x => x.ToInventory()).Where(x => availFullfilmentCentersIds.Contains(x.FulfillmentCenterId)).ToList(); item.Inventory = item.InventoryAll.OrderByDescending(x => Math.Max(0, (x.InStockQuantity ?? 0L) - (x.ReservedQuantity ?? 0L))).FirstOrDefault(); + if (workContext.CurrentStore.DefaultFulfillmentCenterId != null) { - item.Inventory = item.InventoryAll.FirstOrDefault(x => x.FulfillmentCenterId == workContext.CurrentStore.DefaultFulfillmentCenterId); + item.Inventory = item.InventoryAll.FirstOrDefault(x => x.FulfillmentCenterId == workContext.CurrentStore.DefaultFulfillmentCenterId) + ?? item.Inventory; } } } From 78eff44e29894b27f6f2e92b50143ca68ab18ffe Mon Sep 17 00:00:00 2001 From: Andrey Kozlov Date: Tue, 21 Apr 2020 19:32:42 +0500 Subject: [PATCH 2/2] VP-2011: Add EvaluateProductInventories unit test --- .../Inventory/InventoryTests.cs | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 VirtoCommerce.Storefront.Tests/Inventory/InventoryTests.cs diff --git a/VirtoCommerce.Storefront.Tests/Inventory/InventoryTests.cs b/VirtoCommerce.Storefront.Tests/Inventory/InventoryTests.cs new file mode 100644 index 000000000..200b69161 --- /dev/null +++ b/VirtoCommerce.Storefront.Tests/Inventory/InventoryTests.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.Rest; +using Moq; +using VirtoCommerce.Storefront.AutoRestClients.InventoryModuleApi; +using VirtoCommerce.Storefront.AutoRestClients.InventoryModuleApi.Models; +using VirtoCommerce.Storefront.Caching; +using VirtoCommerce.Storefront.Domain; +using VirtoCommerce.Storefront.Infrastructure; +using VirtoCommerce.Storefront.Model; +using VirtoCommerce.Storefront.Model.Catalog; +using VirtoCommerce.Storefront.Model.Stores; +using Xunit; + +namespace VirtoCommerce.Storefront.Tests.Inventory +{ + public class InventoryTests + { + [Fact] + // https://virtocommerce.atlassian.net/browse/VP-2011 + public async Task EvaluateProductInventories_NoDefaultFFCEntry_InventoryInfoFilled() + { + // Arrage + var products = new[] + { + new Product() { Id = "Product1" } + }; + var workContext = new WorkContext() + { + CurrentStore = new Store() + { + DefaultFulfillmentCenterId = "FFC_Default", + AvailFulfillmentCenterIds = new[] { "FFC_Available_1", "FFC_Available_2" }, + }, + }; + var availableInventories = new List() + { + new InventoryInfo() { ProductId = "Product1", FulfillmentCenterId = "FFC_Available_1", InStockQuantity = 3 }, + new InventoryInfo() { ProductId = "Product1", FulfillmentCenterId = "FFC_Available_2", InStockQuantity = 5 }, + }; + var inventoryService = CreateInventoryService(availableInventories); + + // Act + await inventoryService.EvaluateProductInventoriesAsync(products, workContext); + + // Assert + Assert.NotNull(products[0].Inventory); + Assert.Equal("FFC_Available_2", products[0].Inventory.FulfillmentCenterId); + Assert.Equal("Product1", products[0].Inventory.ProductId); + Assert.Equal(5, products[0].Inventory.InStockQuantity); + + Assert.NotNull(products[0].InventoryAll); + Assert.Equal(2, products[0].InventoryAll.Count); + Assert.Equal("FFC_Available_1", products[0].InventoryAll[0].FulfillmentCenterId); + Assert.Equal("Product1", products[0].InventoryAll[0].ProductId); + Assert.Equal(3, products[0].InventoryAll[0].InStockQuantity); + Assert.Equal("FFC_Available_2", products[0].InventoryAll[1].FulfillmentCenterId); + Assert.Equal("Product1", products[0].InventoryAll[1].ProductId); + Assert.Equal(5, products[0].InventoryAll[1].InStockQuantity); + } + + private static InventoryService CreateInventoryService(IEnumerable allInventoryInfos) + { + var inventoryModuleStub = new Mock(); + + inventoryModuleStub.Setup(x => x.GetProductsInventoriesByPlentyIdsWithHttpMessagesAsync(It.IsAny>(), null, It.IsAny())) + .Returns, Dictionary>, CancellationToken>((ids, customHeaders, cancellationToken) => + Task.FromResult( + new HttpOperationResponse>() + { + Body = allInventoryInfos.Where(inventoryInfo => ids.Any(id => id == inventoryInfo.ProductId)).ToList(), + })); + + var storefrontMemoryCache = CreateStorefrontMemoryCache(); + + var apiChangesWatcherStub = new Mock(); + var result = new InventoryService(inventoryModuleStub.Object, storefrontMemoryCache, apiChangesWatcherStub.Object); + + return result; + } + + private static StorefrontMemoryCache CreateStorefrontMemoryCache() + { + var services = new ServiceCollection(); + + services.AddMemoryCache(); + + var serviceProvider = services.BuildServiceProvider(); + var memoryCache = serviceProvider.GetService(); + + var loggerFactoryStub = new Mock(); + var workContextAccessorStub = new Mock(); + var result = new StorefrontMemoryCache(memoryCache, Options.Create(new StorefrontOptions()), loggerFactoryStub.Object, workContextAccessorStub.Object); + + return result; + } + } +}