Browse Source

Fix ProductDetailModificationTime value

pull/143/head
gdlcf88 5 years ago
parent
commit
ec9949660d
  1. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/INewOrderGenerator.cs
  2. 13
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs
  3. 33
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs
  4. 46
      modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs
  5. 8
      modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.TestBase/OrderTestData.cs
  6. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/ProductDetailDto.cs

4
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.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Orders.Orders.Dtos; using EasyAbp.EShop.Orders.Orders.Dtos;
using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.Products.Dtos; using EasyAbp.EShop.Products.Products.Dtos;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
{ {
public interface INewOrderGenerator public interface INewOrderGenerator
{ {
Task<Order> GenerateAsync(Guid customerUserId, CreateOrderDto input, Dictionary<Guid, ProductDto> productDict); Task<Order> GenerateAsync(Guid customerUserId, CreateOrderDto input, Dictionary<Guid, ProductDto> productDict,
Dictionary<Guid, ProductDetailDto> productDetailDict);
} }
} }

13
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.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Orders.Orders.Dtos; using EasyAbp.EShop.Orders.Orders.Dtos;
using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos; using EasyAbp.EShop.Products.Products.Dtos;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -40,13 +41,13 @@ namespace EasyAbp.EShop.Orders.Orders
} }
public virtual async Task<Order> GenerateAsync(Guid customerUserId, CreateOrderDto input, public virtual async Task<Order> GenerateAsync(Guid customerUserId, CreateOrderDto input,
Dictionary<Guid, ProductDto> productDict) Dictionary<Guid, ProductDto> productDict, Dictionary<Guid, ProductDetailDto> productDetailDict)
{ {
var orderLines = new List<OrderLine>(); var orderLines = new List<OrderLine>();
foreach (var inputOrderLine in input.OrderLines) 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); var storeCurrency = await GetStoreCurrencyAsync(input.StoreId);
@ -105,11 +106,15 @@ namespace EasyAbp.EShop.Orders.Orders
} }
protected virtual async Task<OrderLine> GenerateOrderLineAsync(CreateOrderDto input, protected virtual async Task<OrderLine> GenerateOrderLineAsync(CreateOrderDto input,
CreateOrderLineDto inputOrderLine, Dictionary<Guid, ProductDto> productDict) CreateOrderLineDto inputOrderLine, Dictionary<Guid, ProductDto> productDict,
Dictionary<Guid, ProductDetailDto> productDetailDict)
{ {
var product = productDict[inputOrderLine.ProductId]; var product = productDict[inputOrderLine.ProductId];
var productSku = product.GetSkuById(inputOrderLine.ProductSkuId); 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)) if (!inputOrderLine.Quantity.IsBetween(productSku.OrderMinQuantity, productSku.OrderMaxQuantity))
{ {
throw new OrderLineInvalidQuantityException(product.Id, productSku.Id, inputOrderLine.Quantity); throw new OrderLineInvalidQuantityException(product.Id, productSku.Id, inputOrderLine.Quantity);
@ -122,7 +127,7 @@ namespace EasyAbp.EShop.Orders.Orders
productId: product.Id, productId: product.Id,
productSkuId: productSku.Id, productSkuId: productSku.Id,
productModificationTime: product.LastModificationTime ?? product.CreationTime, productModificationTime: product.LastModificationTime ?? product.CreationTime,
productDetailModificationTime: productSku.LastModificationTime ?? productSku.CreationTime, productDetailModificationTime: productDetail?.LastModificationTime ?? productDetail?.CreationTime,
productGroupName: product.ProductGroupName, productGroupName: product.ProductGroupName,
productGroupDisplayName: product.ProductGroupDisplayName, productGroupDisplayName: product.ProductGroupDisplayName,
productUniqueName: product.UniqueName, productUniqueName: product.UniqueName,

33
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 System.Threading.Tasks;
using EasyAbp.EShop.Orders.Authorization; using EasyAbp.EShop.Orders.Authorization;
using EasyAbp.EShop.Orders.Orders.Dtos; 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;
using EasyAbp.EShop.Products.Products.Dtos; using EasyAbp.EShop.Products.Products.Dtos;
using EasyAbp.EShop.Stores.Stores; using EasyAbp.EShop.Stores.Stores;
@ -24,17 +26,20 @@ namespace EasyAbp.EShop.Orders.Orders
private readonly INewOrderGenerator _newOrderGenerator; private readonly INewOrderGenerator _newOrderGenerator;
private readonly IProductAppService _productAppService; private readonly IProductAppService _productAppService;
private readonly IProductDetailAppService _productDetailAppService;
private readonly IOrderManager _orderManager; private readonly IOrderManager _orderManager;
private readonly IOrderRepository _repository; private readonly IOrderRepository _repository;
public OrderAppService( public OrderAppService(
INewOrderGenerator newOrderGenerator, INewOrderGenerator newOrderGenerator,
IProductAppService productAppService, IProductAppService productAppService,
IProductDetailAppService productDetailAppService,
IOrderManager orderManager, IOrderManager orderManager,
IOrderRepository repository) : base(repository) IOrderRepository repository) : base(repository)
{ {
_newOrderGenerator = newOrderGenerator; _newOrderGenerator = newOrderGenerator;
_productAppService = productAppService; _productAppService = productAppService;
_productDetailAppService = productDetailAppService;
_orderManager = orderManager; _orderManager = orderManager;
_repository = repository; _repository = repository;
} }
@ -94,7 +99,18 @@ namespace EasyAbp.EShop.Orders.Orders
new OrderOperationAuthorizationRequirement(OrderOperation.Creation) 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); await DiscountOrderAsync(order, productDict);
@ -116,7 +132,7 @@ namespace EasyAbp.EShop.Orders.Orders
{ {
var dict = new Dictionary<Guid, ProductDto>(); var dict = new Dictionary<Guid, ProductDto>();
foreach (var productId in productIds.Distinct().ToList()) foreach (var productId in productIds.Distinct())
{ {
dict.Add(productId, await _productAppService.GetAsync(productId)); dict.Add(productId, await _productAppService.GetAsync(productId));
} }
@ -124,6 +140,19 @@ namespace EasyAbp.EShop.Orders.Orders
return dict; return dict;
} }
protected virtual async Task<Dictionary<Guid, ProductDetailDto>> GetProductDetailDictionaryAsync(
IEnumerable<Guid> productDetailIds)
{
var dict = new Dictionary<Guid, ProductDetailDto>();
foreach (var productDetailId in productDetailIds.Distinct())
{
dict.Add(productDetailId, await _productDetailAppService.GetAsync(productDetailId));
}
return dict;
}
[RemoteService(false)] [RemoteService(false)]
public override Task<OrderDto> UpdateAsync(Guid id, CreateOrderDto input) public override Task<OrderDto> UpdateAsync(Guid id, CreateOrderDto input)
{ {

46
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.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Orders.Orders.Dtos; 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;
using EasyAbp.EShop.Products.Products.Dtos; using EasyAbp.EShop.Products.Products.Dtos;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -33,10 +35,12 @@ namespace EasyAbp.EShop.Orders.Orders
CreationTime = DateTime.Now, CreationTime = DateTime.Now,
IsPublished = true, IsPublished = true,
Id = OrderTestData.Product1Id, Id = OrderTestData.Product1Id,
StoreId = OrderTestData.Store1Id,
ProductGroupName = "Default", ProductGroupName = "Default",
ProductGroupDisplayName = "Default", ProductGroupDisplayName = "Default",
UniqueName = "Pencil", UniqueName = "Pencil",
DisplayName = "Hello pencil", DisplayName = "Hello pencil",
ProductDetailId = OrderTestData.ProductDetail1Id,
ProductSkus = new List<ProductSkuDto> ProductSkus = new List<ProductSkuDto>
{ {
new ProductSkuDto new ProductSkuDto
@ -48,6 +52,18 @@ namespace EasyAbp.EShop.Orders.Orders
AttributeOptionIds = new List<Guid>(), AttributeOptionIds = new List<Guid>(),
Price = 1m, Price = 1m,
Currency = "CNY", Currency = "CNY",
ProductDetailId = null
},
new ProductSkuDto
{
Id = OrderTestData.ProductSku2Id,
Name = "My SKU 2",
OrderMinQuantity = 0,
OrderMaxQuantity = 100,
AttributeOptionIds = new List<Guid>(),
Price = 2m,
Currency = "CNY",
ProductDetailId = OrderTestData.ProductDetail2Id
} }
}, },
InventoryStrategy = InventoryStrategy.NoNeed, InventoryStrategy = InventoryStrategy.NoNeed,
@ -55,6 +71,28 @@ namespace EasyAbp.EShop.Orders.Orders
})); }));
services.AddTransient(_ => productAppService); services.AddTransient(_ => productAppService);
var productDetailAppService = Substitute.For<IProductDetailAppService>();
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] [Fact]
@ -76,8 +114,13 @@ namespace EasyAbp.EShop.Orders.Orders
} }
}; };
OrderDto createResponse = null;
// Act // Act
var createResponse = await _orderAppService.CreateAsync(createOrderDto); await WithUnitOfWorkAsync(async () =>
{
createResponse = await _orderAppService.CreateAsync(createOrderDto);
});
var response = await _orderAppService.GetAsync(createResponse.Id); var response = await _orderAppService.GetAsync(createResponse.Id);
// Assert // Assert
@ -118,6 +161,7 @@ namespace EasyAbp.EShop.Orders.Orders
responseOrderLine.Currency.ShouldBe("CNY"); responseOrderLine.Currency.ShouldBe("CNY");
responseOrderLine.Quantity.ShouldBe(10); responseOrderLine.Quantity.ShouldBe(10);
responseOrderLine.ProductModificationTime.ShouldBe(OrderTestData.ProductLastModificationTime); responseOrderLine.ProductModificationTime.ShouldBe(OrderTestData.ProductLastModificationTime);
responseOrderLine.ProductDetailModificationTime.ShouldBe(OrderTestData.ProductDetailLastModificationTime);
responseOrderLine.RefundAmount.ShouldBe(0m); responseOrderLine.RefundAmount.ShouldBe(0m);
responseOrderLine.RefundedQuantity.ShouldBe(0); responseOrderLine.RefundedQuantity.ShouldBe(0);

8
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 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 ProductLastModificationTime { get; } = DateTime.Today;
public static DateTime ProductDetailLastModificationTime { get; } = DateTime.Today;
} }
} }

2
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 namespace EasyAbp.EShop.Products.ProductDetails.Dtos
{ {
[Serializable] [Serializable]
public class ProductDetailDto : ExtensibleEntityDto<Guid> public class ProductDetailDto : ExtensibleFullAuditedEntityDto<Guid>
{ {
public Guid? StoreId { get; set; } public Guid? StoreId { get; set; }

Loading…
Cancel
Save