From ec9949660d1e2b74a8a8792ec51032aff8ee6d34 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Tue, 12 Apr 2022 04:46:33 +0800 Subject: [PATCH] Fix ProductDetailModificationTime value --- .../EShop/Orders/Orders/INewOrderGenerator.cs | 4 +- .../EShop/Orders/Orders/NewOrderGenerator.cs | 13 ++++-- .../EShop/Orders/Orders/OrderAppService.cs | 33 ++++++++++++- .../Orders/OrderAppServiceTests.cs | 46 ++++++++++++++++++- .../OrderTestData.cs | 8 ++++ .../ProductDetails/Dtos/ProductDetailDto.cs | 2 +- 6 files changed, 97 insertions(+), 9 deletions(-) diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/INewOrderGenerator.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/INewOrderGenerator.cs index ad460246..1d7cd9ad 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/INewOrderGenerator.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/INewOrderGenerator.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using System.Threading.Tasks; using EasyAbp.EShop.Orders.Orders.Dtos; +using EasyAbp.EShop.Products.ProductDetails.Dtos; using EasyAbp.EShop.Products.Products.Dtos; namespace EasyAbp.EShop.Orders.Orders { public interface INewOrderGenerator { - Task GenerateAsync(Guid customerUserId, CreateOrderDto input, Dictionary productDict); + Task GenerateAsync(Guid customerUserId, CreateOrderDto input, Dictionary productDict, + Dictionary productDetailDict); } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs index 1ca98639..906fb5c2 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using EasyAbp.EShop.Orders.Orders.Dtos; +using EasyAbp.EShop.Products.ProductDetails.Dtos; using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products.Dtos; using Microsoft.Extensions.DependencyInjection; @@ -40,13 +41,13 @@ namespace EasyAbp.EShop.Orders.Orders } public virtual async Task GenerateAsync(Guid customerUserId, CreateOrderDto input, - Dictionary productDict) + Dictionary productDict, Dictionary productDetailDict) { var orderLines = new List(); foreach (var inputOrderLine in input.OrderLines) { - orderLines.Add(await GenerateOrderLineAsync(input, inputOrderLine, productDict)); + orderLines.Add(await GenerateOrderLineAsync(input, inputOrderLine, productDict, productDetailDict)); } var storeCurrency = await GetStoreCurrencyAsync(input.StoreId); @@ -105,11 +106,15 @@ namespace EasyAbp.EShop.Orders.Orders } protected virtual async Task GenerateOrderLineAsync(CreateOrderDto input, - CreateOrderLineDto inputOrderLine, Dictionary productDict) + CreateOrderLineDto inputOrderLine, Dictionary productDict, + Dictionary productDetailDict) { var product = productDict[inputOrderLine.ProductId]; var productSku = product.GetSkuById(inputOrderLine.ProductSkuId); + var productDetailId = productSku.ProductDetailId ?? product.ProductDetailId; + var productDetail = productDetailId.HasValue ? productDetailDict[productDetailId.Value] : null; + if (!inputOrderLine.Quantity.IsBetween(productSku.OrderMinQuantity, productSku.OrderMaxQuantity)) { throw new OrderLineInvalidQuantityException(product.Id, productSku.Id, inputOrderLine.Quantity); @@ -122,7 +127,7 @@ namespace EasyAbp.EShop.Orders.Orders productId: product.Id, productSkuId: productSku.Id, productModificationTime: product.LastModificationTime ?? product.CreationTime, - productDetailModificationTime: productSku.LastModificationTime ?? productSku.CreationTime, + productDetailModificationTime: productDetail?.LastModificationTime ?? productDetail?.CreationTime, productGroupName: product.ProductGroupName, productGroupDisplayName: product.ProductGroupDisplayName, productUniqueName: product.UniqueName, diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs index 90f9c5c8..2e432276 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Threading.Tasks; using EasyAbp.EShop.Orders.Authorization; using EasyAbp.EShop.Orders.Orders.Dtos; +using EasyAbp.EShop.Products.ProductDetails; +using EasyAbp.EShop.Products.ProductDetails.Dtos; using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products.Dtos; using EasyAbp.EShop.Stores.Stores; @@ -24,17 +26,20 @@ namespace EasyAbp.EShop.Orders.Orders private readonly INewOrderGenerator _newOrderGenerator; private readonly IProductAppService _productAppService; + private readonly IProductDetailAppService _productDetailAppService; private readonly IOrderManager _orderManager; private readonly IOrderRepository _repository; public OrderAppService( INewOrderGenerator newOrderGenerator, IProductAppService productAppService, + IProductDetailAppService productDetailAppService, IOrderManager orderManager, IOrderRepository repository) : base(repository) { _newOrderGenerator = newOrderGenerator; _productAppService = productAppService; + _productDetailAppService = productDetailAppService; _orderManager = orderManager; _repository = repository; } @@ -94,7 +99,18 @@ namespace EasyAbp.EShop.Orders.Orders new OrderOperationAuthorizationRequirement(OrderOperation.Creation) ); - var order = await _newOrderGenerator.GenerateAsync(CurrentUser.GetId(), input, productDict); + var productDetailIds = input.OrderLines + .Select(dto => + productDict[dto.ProductId].GetSkuById(dto.ProductSkuId).ProductDetailId ?? + productDict[dto.ProductId].ProductDetailId) + .Where(x => x.HasValue) + .Select(x => x.Value) + .ToList(); + + var productDetailDict = await GetProductDetailDictionaryAsync(productDetailIds); + + // Todo: Can we use IProductDataScopedCache/IProductDetailDataScopedCache instead of productDict/productDetailDict? + var order = await _newOrderGenerator.GenerateAsync(CurrentUser.GetId(), input, productDict, productDetailDict); await DiscountOrderAsync(order, productDict); @@ -116,7 +132,7 @@ namespace EasyAbp.EShop.Orders.Orders { var dict = new Dictionary(); - foreach (var productId in productIds.Distinct().ToList()) + foreach (var productId in productIds.Distinct()) { dict.Add(productId, await _productAppService.GetAsync(productId)); } @@ -124,6 +140,19 @@ namespace EasyAbp.EShop.Orders.Orders return dict; } + protected virtual async Task> GetProductDetailDictionaryAsync( + IEnumerable productDetailIds) + { + var dict = new Dictionary(); + + foreach (var productDetailId in productDetailIds.Distinct()) + { + dict.Add(productDetailId, await _productDetailAppService.GetAsync(productDetailId)); + } + + return dict; + } + [RemoteService(false)] public override Task UpdateAsync(Guid id, CreateOrderDto input) { diff --git a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs index b97efae5..f69a4998 100644 --- a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs +++ b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using EasyAbp.EShop.Orders.Orders.Dtos; +using EasyAbp.EShop.Products.ProductDetails; +using EasyAbp.EShop.Products.ProductDetails.Dtos; using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products.Dtos; using Microsoft.EntityFrameworkCore; @@ -33,10 +35,12 @@ namespace EasyAbp.EShop.Orders.Orders CreationTime = DateTime.Now, IsPublished = true, Id = OrderTestData.Product1Id, + StoreId = OrderTestData.Store1Id, ProductGroupName = "Default", ProductGroupDisplayName = "Default", UniqueName = "Pencil", DisplayName = "Hello pencil", + ProductDetailId = OrderTestData.ProductDetail1Id, ProductSkus = new List { new ProductSkuDto @@ -48,6 +52,18 @@ namespace EasyAbp.EShop.Orders.Orders AttributeOptionIds = new List(), Price = 1m, Currency = "CNY", + ProductDetailId = null + }, + new ProductSkuDto + { + Id = OrderTestData.ProductSku2Id, + Name = "My SKU 2", + OrderMinQuantity = 0, + OrderMaxQuantity = 100, + AttributeOptionIds = new List(), + Price = 2m, + Currency = "CNY", + ProductDetailId = OrderTestData.ProductDetail2Id } }, InventoryStrategy = InventoryStrategy.NoNeed, @@ -55,6 +71,28 @@ namespace EasyAbp.EShop.Orders.Orders })); services.AddTransient(_ => productAppService); + + var productDetailAppService = Substitute.For(); + + productDetailAppService.GetAsync(OrderTestData.ProductDetail1Id).Returns(Task.FromResult( + new ProductDetailDto + { + Id = OrderTestData.ProductDetail1Id, + CreationTime = OrderTestData.ProductDetailLastModificationTime, + LastModificationTime = OrderTestData.ProductDetailLastModificationTime, + StoreId = OrderTestData.Store1Id, + Description = "My Details 1" + })); + + productDetailAppService.GetAsync(OrderTestData.ProductDetail2Id).Returns(Task.FromResult( + new ProductDetailDto + { + Id = OrderTestData.ProductDetail2Id, + StoreId = OrderTestData.Store1Id, + Description = "My Details 2" + })); + + services.AddTransient(_ => productDetailAppService); } [Fact] @@ -76,8 +114,13 @@ namespace EasyAbp.EShop.Orders.Orders } }; + OrderDto createResponse = null; // Act - var createResponse = await _orderAppService.CreateAsync(createOrderDto); + await WithUnitOfWorkAsync(async () => + { + createResponse = await _orderAppService.CreateAsync(createOrderDto); + }); + var response = await _orderAppService.GetAsync(createResponse.Id); // Assert @@ -118,6 +161,7 @@ namespace EasyAbp.EShop.Orders.Orders responseOrderLine.Currency.ShouldBe("CNY"); responseOrderLine.Quantity.ShouldBe(10); responseOrderLine.ProductModificationTime.ShouldBe(OrderTestData.ProductLastModificationTime); + responseOrderLine.ProductDetailModificationTime.ShouldBe(OrderTestData.ProductDetailLastModificationTime); responseOrderLine.RefundAmount.ShouldBe(0m); responseOrderLine.RefundedQuantity.ShouldBe(0); diff --git a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.TestBase/OrderTestData.cs b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.TestBase/OrderTestData.cs index 05851986..b15a517a 100644 --- a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.TestBase/OrderTestData.cs +++ b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.TestBase/OrderTestData.cs @@ -11,6 +11,14 @@ namespace EasyAbp.EShop.Orders public static Guid ProductSku1Id { get; } = Guid.NewGuid(); + public static Guid ProductSku2Id { get; } = Guid.NewGuid(); + + public static Guid ProductDetail1Id { get; } = Guid.NewGuid(); + + public static Guid ProductDetail2Id { get; } = Guid.NewGuid(); + public static DateTime ProductLastModificationTime { get; } = DateTime.Today; + + public static DateTime ProductDetailLastModificationTime { get; } = DateTime.Today; } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/ProductDetailDto.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/ProductDetailDto.cs index 54925731..5175ca6a 100644 --- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/ProductDetailDto.cs +++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/ProductDetailDto.cs @@ -4,7 +4,7 @@ using Volo.Abp.Application.Dtos; namespace EasyAbp.EShop.Products.ProductDetails.Dtos { [Serializable] - public class ProductDetailDto : ExtensibleEntityDto + public class ProductDetailDto : ExtensibleFullAuditedEntityDto { public Guid? StoreId { get; set; }