diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs index fe7ce521..20a76dca 100644 --- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs +++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs @@ -451,5 +451,32 @@ namespace EasyAbp.EShop.Products.Products } ).ToList())); } + + protected override ProductDto MapToGetOutputDto(Product entity) + { + var productDto = base.MapToGetOutputDto(entity); + + return SortAttributesAndOptions(productDto); + } + + protected override ProductDto MapToGetListOutputDto(Product entity) + { + var productDto = base.MapToGetListOutputDto(entity); + + return SortAttributesAndOptions(productDto); + } + + protected virtual ProductDto SortAttributesAndOptions(ProductDto productDto) + { + productDto.ProductAttributes = productDto.ProductAttributes.OrderByDescending(x => x.DisplayOrder).ToList(); + + foreach (var productAttributeDto in productDto.ProductAttributes) + { + productAttributeDto.ProductAttributeOptions = productAttributeDto.ProductAttributeOptions + .OrderByDescending(x => x.DisplayOrder).ToList(); + } + + return productDto; + } } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductAppServiceTests.cs b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductAppServiceTests.cs index f7c53551..57cc997f 100644 --- a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductAppServiceTests.cs +++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductAppServiceTests.cs @@ -199,7 +199,8 @@ namespace EasyAbp.EShop.Products.Products { await _productAppService.CreateSkuAsync(ProductsTestData.Product1Id, new CreateProductSkuDto { - AttributeOptionIds = new List {ProductsTestData.Product1Attribute1Option4Id}, + AttributeOptionIds = new List + { ProductsTestData.Product1Attribute1Option4Id, ProductsTestData.Product1Attribute2Option1Id }, ProductDetailId = wrongProductDetailId, Currency = "CNY", Price = 10m, @@ -208,5 +209,27 @@ namespace EasyAbp.EShop.Products.Products }); })).EntityType.ShouldBe(typeof(ProductDetail)); } + + [Fact] + public async Task Should_Get_Orderly_ProductAttributes_And_ProductAttributeOptions() + { + var productDto = await _productAppService.GetAsync(ProductsTestData.Product1Id); + + productDto.ProductAttributes.Count.ShouldBe(2); + + var size = productDto.ProductAttributes[0]; + var color = productDto.ProductAttributes[1]; + + size.DisplayName.ShouldBe("Size"); + color.DisplayName.ShouldBe("Color"); + + size.ProductAttributeOptions[0].DisplayName.ShouldBe("S"); + size.ProductAttributeOptions[1].DisplayName.ShouldBe("M"); + size.ProductAttributeOptions[2].DisplayName.ShouldBe("L"); + size.ProductAttributeOptions[3].DisplayName.ShouldBe("XL"); + + color.ProductAttributeOptions[0].DisplayName.ShouldBe("Red"); + color.ProductAttributeOptions[1].DisplayName.ShouldBe("Green"); + } } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestData.cs b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestData.cs index 4a0ef23f..78d9c339 100644 --- a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestData.cs +++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestData.cs @@ -16,6 +16,8 @@ namespace EasyAbp.EShop.Products public static Guid Product1Attribute1Id { get; } = Guid.NewGuid(); + public static Guid Product1Attribute2Id { get; } = Guid.NewGuid(); + public static Guid Product1Attribute1Option1Id { get; } = Guid.NewGuid(); public static Guid Product1Attribute1Option2Id { get; } = Guid.NewGuid(); @@ -24,6 +26,10 @@ namespace EasyAbp.EShop.Products public static Guid Product1Attribute1Option4Id { get; } = Guid.NewGuid(); + public static Guid Product1Attribute2Option1Id { get; } = Guid.NewGuid(); + + public static Guid Product1Attribute2Option2Id { get; } = Guid.NewGuid(); + public static Guid Product1Sku1Id { get; } = Guid.NewGuid(); public static Guid Product1Sku2Id { get; } = Guid.NewGuid(); diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestDataBuilder.cs b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestDataBuilder.cs index 56dfb166..b26cae67 100644 --- a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestDataBuilder.cs +++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestDataBuilder.cs @@ -47,31 +47,42 @@ namespace EasyAbp.EShop.Products var product = new Product(ProductsTestData.Product1Id, null, ProductsTestData.Store1Id, "Default", productDetail1.Id, "Cake", "Cake", InventoryStrategy.NoNeed, true, false, false, null, null, 0); - var attribute = new ProductAttribute(ProductsTestData.Product1Attribute1Id, "Size", null); + var attribute1 = new ProductAttribute(ProductsTestData.Product1Attribute1Id, "Size", null, 2); + var attribute2 = new ProductAttribute(ProductsTestData.Product1Attribute2Id, "Color", null, 1); - attribute.ProductAttributeOptions.AddRange(new[] + attribute1.ProductAttributeOptions.AddRange(new[] { - new ProductAttributeOption(ProductsTestData.Product1Attribute1Option1Id, "S", null), - new ProductAttributeOption(ProductsTestData.Product1Attribute1Option2Id, "M", null), - new ProductAttributeOption(ProductsTestData.Product1Attribute1Option3Id, "L", null), - new ProductAttributeOption(ProductsTestData.Product1Attribute1Option4Id, "XL", null) + new ProductAttributeOption(ProductsTestData.Product1Attribute1Option4Id, "XL", null, 1), + new ProductAttributeOption(ProductsTestData.Product1Attribute1Option2Id, "M", null, 3), + new ProductAttributeOption(ProductsTestData.Product1Attribute1Option1Id, "S", null, 4), + new ProductAttributeOption(ProductsTestData.Product1Attribute1Option3Id, "L", null, 2), }); - - product.ProductAttributes.Add(attribute); + attribute2.ProductAttributeOptions.AddRange(new[] + { + new ProductAttributeOption(ProductsTestData.Product1Attribute2Option2Id, "Green", null, 1), + new ProductAttributeOption(ProductsTestData.Product1Attribute2Option1Id, "Red", null, 2), + }); + + product.ProductAttributes.Add(attribute2); + product.ProductAttributes.Add(attribute1); + await _productManager.CreateAsync(product); var productSku1 = new ProductSku(ProductsTestData.Product1Sku1Id, await _attributeOptionIdsSerializer.SerializeAsync(new[] - { ProductsTestData.Product1Attribute1Option1Id }), null, "CNY", null, 1m, 1, 10, null, null, null); - + { ProductsTestData.Product1Attribute1Option1Id, ProductsTestData.Product1Attribute2Option1Id }), + null, "CNY", null, 1m, 1, 10, null, null, null); + var productSku2 = new ProductSku(ProductsTestData.Product1Sku2Id, await _attributeOptionIdsSerializer.SerializeAsync(new[] - { ProductsTestData.Product1Attribute1Option2Id }), null, "CNY", null, 2m, 1, 10, null, null, null); - + { ProductsTestData.Product1Attribute1Option2Id, ProductsTestData.Product1Attribute2Option1Id }), + null, "CNY", null, 2m, 1, 10, null, null, null); + var productSku3 = new ProductSku(ProductsTestData.Product1Sku3Id, await _attributeOptionIdsSerializer.SerializeAsync(new[] - { ProductsTestData.Product1Attribute1Option3Id }), null, "CNY", null, 3m, 1, 10, null, null, null); + { ProductsTestData.Product1Attribute1Option3Id, ProductsTestData.Product1Attribute2Option2Id }), + null, "CNY", null, 3m, 1, 10, null, null, null); await _productManager.CreateSkuAsync(product, productSku1); await _productManager.CreateSkuAsync(product, productSku2);