Browse Source

Make ProductDetail non-essential and reusable

pull/143/head
gdlcf88 5 years ago
parent
commit
b4f89de6d3
  1. 2
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/OrderLineDto.cs
  2. 2
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Orders/IOrderLine.cs
  3. 2
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Orders/OrderLineEto.cs
  4. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderLine.cs
  5. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/CreateUpdateProductDto.cs
  6. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductDto.cs
  7. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductViewDto.cs
  8. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/cs.json
  9. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
  10. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pl.json
  11. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pt-BR.json
  12. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/sl.json
  13. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/tr.json
  14. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/vi.json
  15. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
  16. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
  17. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProduct.cs
  18. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/ProductEto.cs
  19. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductsErrorCodes.cs
  20. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/Product.cs
  21. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductDetailHasBeenUsedException.cs
  22. 33
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs
  23. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductView.cs
  24. 15
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/CreateModal.cshtml.cs
  25. 49
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/EditModal.cshtml.cs
  26. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateEditProductDetailViewModel.cs
  27. 110
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Domain.Tests/Products/ProductDomainTests.cs
  28. 2
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestData.cs
  29. 5131
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/20220411111127_MadeProductDetailIdNullable.Designer.cs
  30. 70
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/20220411111127_MadeProductDetailIdNullable.cs
  31. 8
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/EShopSampleDbContextModelSnapshot.cs

2
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/OrderLineDto.cs

@ -15,7 +15,7 @@ namespace EasyAbp.EShop.Orders.Orders.Dtos
public DateTime ProductModificationTime { get; set; }
public DateTime ProductDetailModificationTime { get; set; }
public DateTime? ProductDetailModificationTime { get; set; }
public string ProductGroupName { get; set; }

2
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Orders/IOrderLine.cs

@ -11,7 +11,7 @@ namespace EasyAbp.EShop.Orders.Orders
DateTime ProductModificationTime { get; }
DateTime ProductDetailModificationTime { get; }
DateTime? ProductDetailModificationTime { get; }
string ProductGroupName { get; }

2
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Orders/OrderLineEto.cs

@ -14,7 +14,7 @@ namespace EasyAbp.EShop.Orders.Orders
public DateTime ProductModificationTime { get; set; }
public DateTime ProductDetailModificationTime { get; set; }
public DateTime? ProductDetailModificationTime { get; set; }
public string ProductGroupName { get; set; }

4
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderLine.cs

@ -15,7 +15,7 @@ namespace EasyAbp.EShop.Orders.Orders
public virtual DateTime ProductModificationTime { get; protected set; }
public virtual DateTime ProductDetailModificationTime { get; protected set; }
public virtual DateTime? ProductDetailModificationTime { get; protected set; }
[NotNull]
public virtual string ProductGroupName { get; protected set; }
@ -69,7 +69,7 @@ namespace EasyAbp.EShop.Orders.Orders
Guid productId,
Guid productSkuId,
DateTime productModificationTime,
DateTime productDetailModificationTime,
DateTime? productDetailModificationTime,
[NotNull] string productGroupName,
[NotNull] string productGroupDisplayName,
[CanBeNull] string productUniqueName,

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/CreateUpdateProductDto.cs

@ -18,7 +18,7 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public string ProductGroupName { get; set; }
[DisplayName("ProductDetailId")]
public Guid ProductDetailId { get; set; }
public Guid? ProductDetailId { get; set; }
[DisplayName("ProductCategory")]
public ICollection<Guid> CategoryIds { get; set; }

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductDto.cs

@ -14,7 +14,7 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public string ProductGroupDisplayName { get; set; }
public Guid ProductDetailId { get; set; }
public Guid? ProductDetailId { get; set; }
public string UniqueName { get; set; }

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductViewDto.cs

@ -11,7 +11,7 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public string ProductGroupName { get; set; }
public Guid ProductDetailId { get; set; }
public Guid? ProductDetailId { get; set; }
public string UniqueName { get; set; }

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/cs.json

@ -86,7 +86,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "The product unique name '{uniqueName}' is duplicated.",
"EasyAbp.EShop.Products:InventoryChangeFailed": "Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}",
"EasyAbp.EShop.Products:NonexistentProductGroup": "The specified product group ({productGroupName}) is nonexistent.",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "ProductDetail {productDetailId} has been used.",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "Sku code {code} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "Sku {serializedAttributeOptionIds} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "You have no permission to get category list with hidden categories.",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json

@ -87,7 +87,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "The product unique name '{uniqueName}' is duplicated.",
"EasyAbp.EShop.Products:InventoryChangeFailed": "Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}",
"EasyAbp.EShop.Products:NonexistentProductGroup": "The specified product group ({productGroupName}) is nonexistent.",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "ProductDetail {productDetailId} has been used.",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "Sku code {code} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "Sku {serializedAttributeOptionIds} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "You have no permission to get category list with hidden categories.",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pl.json

@ -86,7 +86,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "The product unique name '{uniqueName}' is duplicated.",
"EasyAbp.EShop.Products:InventoryChangeFailed": "Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}",
"EasyAbp.EShop.Products:NonexistentProductGroup": "The specified product group ({productGroupName}) is nonexistent.",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "ProductDetail {productDetailId} has been used.",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "Sku code {code} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "Sku {serializedAttributeOptionIds} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "You have no permission to get category list with hidden categories.",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pt-BR.json

@ -86,7 +86,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "The product unique name '{uniqueName}' is duplicated.",
"EasyAbp.EShop.Products:InventoryChangeFailed": "Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}",
"EasyAbp.EShop.Products:NonexistentProductGroup": "The specified product group ({productGroupName}) is nonexistent.",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "ProductDetail {productDetailId} has been used.",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "Sku code {code} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "Sku {serializedAttributeOptionIds} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "You have no permission to get category list with hidden categories.",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/sl.json

@ -87,7 +87,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "The product unique name '{uniqueName}' is duplicated.",
"EasyAbp.EShop.Products:InventoryChangeFailed": "Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}",
"EasyAbp.EShop.Products:NonexistentProductGroup": "The specified product group ({productGroupName}) is nonexistent.",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "ProductDetail {productDetailId} has been used.",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "Sku code {code} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "Sku {serializedAttributeOptionIds} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "You have no permission to get category list with hidden categories.",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/tr.json

@ -87,7 +87,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "The product unique name '{uniqueName}' is duplicated.",
"EasyAbp.EShop.Products:InventoryChangeFailed": "Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}",
"EasyAbp.EShop.Products:NonexistentProductGroup": "The specified product group ({productGroupName}) is nonexistent.",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "ProductDetail {productDetailId} has been used.",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "Sku code {code} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "Sku {serializedAttributeOptionIds} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "You have no permission to get category list with hidden categories.",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/vi.json

@ -86,7 +86,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "The product unique name '{uniqueName}' is duplicated.",
"EasyAbp.EShop.Products:InventoryChangeFailed": "Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}",
"EasyAbp.EShop.Products:NonexistentProductGroup": "The specified product group ({productGroupName}) is nonexistent.",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "ProductDetail {productDetailId} has been used.",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "Sku code {code} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "Sku {serializedAttributeOptionIds} is duplicate for the product {productId}",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "You have no permission to get category list with hidden categories.",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json

@ -84,7 +84,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "唯一的产品名称'{uniqueName}'重复",
"EasyAbp.EShop.Products:InventoryChangeFailed": "产品{productId} (SKU: {productSkuId})的库存不能由{originalInventory}中的{changedInventory}更改",
"EasyAbp.EShop.Products:NonexistentProductGroup": "指定的产品组({productGroupName})不存在",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "商品详情{productDetailId}已被使用",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "商品{productId}的Sku代码{code}重复",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "商品{productId}的Sku{serializedAttributeOptionIds}重复",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "您没有权限获取带有隐藏类别的类别列表",

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json

@ -84,7 +84,6 @@
"EasyAbp.EShop.Products:DuplicatedProductUniqueName": "唯一的產品名稱'{uniqueName}'重復",
"EasyAbp.EShop.Products:InventoryChangeFailed": "產品{productId} (SKU: {productSkuId})的庫存不能由{originalInventory}中的{changedInventory}更改",
"EasyAbp.EShop.Products:NonexistentProductGroup": "指定的產品組({productGroupName})不存在",
"EasyAbp.EShop.Products:ProductDetailHasBeenUsed": "商品詳情{productDetailId}已被使用",
"EasyAbp.EShop.Products:ProductSkuCodeDuplicated": "商品{productId}的Sku代碼{code}重復",
"EasyAbp.EShop.Products:ProductSkuDuplicated": "商品{productId}的Sku{serializedAttributeOptionIds}重復",
"EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden": "您沒有權限獲取帶有隱藏類別的類別列表",

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProduct.cs

@ -8,7 +8,7 @@ namespace EasyAbp.EShop.Products.Products
{
string ProductGroupName { get; }
Guid ProductDetailId { get; }
Guid? ProductDetailId { get; }
string UniqueName { get; }

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/ProductEto.cs

@ -16,7 +16,7 @@ namespace EasyAbp.EShop.Products.Products
public string ProductGroupName { get; set; }
public Guid ProductDetailId { get; set; }
public Guid? ProductDetailId { get; set; }
public string UniqueName { get; set; }

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductsErrorCodes.cs

@ -6,7 +6,6 @@
public const string DuplicatedProductUniqueName = "EasyAbp.EShop.Products:DuplicatedProductUniqueName";
public const string InventoryChangeFailed = "EasyAbp.EShop.Products:InventoryChangeFailed";
public const string NonexistentProductGroup = "EasyAbp.EShop.Products:NonexistentProductGroup";
public const string ProductDetailHasBeenUsed = "EasyAbp.EShop.Products:ProductDetailHasBeenUsed";
public const string ProductSkuCodeDuplicated = "EasyAbp.EShop.Products:ProductSkuCodeDuplicated";
public const string ProductSkuDuplicated = "EasyAbp.EShop.Products:ProductSkuDuplicated";
public const string NotAllowedToGetCategoryListWithShowHidden = "EasyAbp.EShop.Products:NotAllowedToGetCategoryListWithShowHidden";

4
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/Product.cs

@ -15,7 +15,7 @@ namespace EasyAbp.EShop.Products.Products
[NotNull]
public virtual string ProductGroupName { get; protected set; }
public virtual Guid ProductDetailId { get; protected set; }
public virtual Guid? ProductDetailId { get; protected set; }
[CanBeNull]
public virtual string UniqueName { get; protected set; }
@ -51,7 +51,7 @@ namespace EasyAbp.EShop.Products.Products
Guid? tenantId,
Guid storeId,
[NotNull] string productGroupName,
Guid productDetailId,
Guid? productDetailId,
[CanBeNull] string uniqueName,
[NotNull] string displayName,
InventoryStrategy inventoryStrategy,

13
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductDetailHasBeenUsedException.cs

@ -1,13 +0,0 @@
using System;
using Volo.Abp;
namespace EasyAbp.EShop.Products.Products
{
public class ProductDetailHasBeenUsedException : BusinessException
{
public ProductDetailHasBeenUsedException(Guid productDetailId) : base(ProductsErrorCodes.ProductDetailHasBeenUsed)
{
WithData(nameof(productDetailId), productDetailId);
}
}
}

33
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs

@ -4,7 +4,9 @@ using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Options.ProductGroups;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.ProductDetails;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Services;
using Volo.Abp.Uow;
@ -14,6 +16,7 @@ namespace EasyAbp.EShop.Products.Products
{
private readonly IProductRepository _productRepository;
private readonly IProductPriceProvider _productPriceProvider;
private readonly IProductDetailRepository _productDetailRepository;
private readonly IProductCategoryRepository _productCategoryRepository;
private readonly IProductInventoryProvider _productInventoryProvider;
private readonly IProductGroupConfigurationProvider _productGroupConfigurationProvider;
@ -21,12 +24,14 @@ namespace EasyAbp.EShop.Products.Products
public ProductManager(
IProductRepository productRepository,
IProductPriceProvider productPriceProvider,
IProductDetailRepository productDetailRepository,
IProductCategoryRepository productCategoryRepository,
IProductInventoryProvider productInventoryProvider,
IProductGroupConfigurationProvider productGroupConfigurationProvider)
{
_productRepository = productRepository;
_productPriceProvider = productPriceProvider;
_productDetailRepository = productDetailRepository;
_productCategoryRepository = productCategoryRepository;
_productInventoryProvider = productInventoryProvider;
_productGroupConfigurationProvider = productGroupConfigurationProvider;
@ -43,7 +48,7 @@ namespace EasyAbp.EShop.Products.Products
await _productRepository.InsertAsync(product, autoSave: true);
await CheckProductDetailAvailableAsync(product.Id, product.ProductDetailId);
await CheckProductDetailAsync(product);
await UpdateProductCategoriesAsync(product.Id, categoryIds);
@ -69,7 +74,7 @@ namespace EasyAbp.EShop.Products.Products
await _productRepository.UpdateAsync(product, autoSave: true);
await CheckProductDetailAvailableAsync(product.Id, product.ProductDetailId);
await CheckProductDetailAsync(product);
await UpdateProductCategoriesAsync(product.Id, categoryIds);
@ -157,17 +162,27 @@ namespace EasyAbp.EShop.Products.Products
await _productRepository.CheckUniqueNameAsync(product);
}
protected virtual async Task CheckProductDetailAsync(Product product)
{
if (product.ProductDetailId.HasValue)
{
await CheckProductDetailExistAsync(product.ProductDetailId.Value, product.StoreId);
}
foreach (var sku in product.ProductSkus.Where(x => x.ProductDetailId.HasValue))
{
await CheckProductDetailExistAsync(sku.ProductDetailId!.Value, product.StoreId);
}
}
[UnitOfWork]
protected virtual async Task CheckProductDetailAvailableAsync(Guid currentProductId, Guid desiredProductDetailId)
protected virtual async Task CheckProductDetailExistAsync(Guid productDetailId, Guid storeId)
{
var otherOwner = await _productRepository.FindAsync(x =>
x.ProductDetailId == desiredProductDetailId && x.Id != currentProductId);
var productDetail = await _productDetailRepository.GetAsync(productDetailId);
// Todo: should also check ProductSku owner
if (otherOwner != null)
if (productDetail.StoreId.HasValue && productDetail.StoreId.Value != storeId)
{
throw new ProductDetailHasBeenUsedException(desiredProductDetailId);
throw new EntityNotFoundException(typeof(ProductDetail), productDetailId);
}
}

4
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductView.cs

@ -14,7 +14,7 @@ namespace EasyAbp.EShop.Products.Products
public virtual string ProductGroupName { get; protected set; }
public virtual Guid ProductDetailId { get; protected set; }
public virtual Guid? ProductDetailId { get; protected set; }
public virtual string UniqueName { get; protected set; }
@ -51,7 +51,7 @@ namespace EasyAbp.EShop.Products.Products
Guid? tenantId,
Guid storeId,
string productGroupName,
Guid productDetailId,
Guid? productDetailId,
string uniqueName,
string displayName,
InventoryStrategy inventoryStrategy,

15
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/CreateModal.cshtml.cs

@ -73,15 +73,18 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
public virtual async Task<IActionResult> OnPostAsync()
{
var detail = await _productDetailAppService.CreateAsync(
ObjectMapper
.Map<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>(Product.ProductDetail));
var createDto = ObjectMapper.Map<CreateEditProductViewModel, CreateUpdateProductDto>(Product);
createDto.ProductDetailId = detail.Id;
if (Product.ProductDetail.HasContent())
{
var detail = await _productDetailAppService.CreateAsync(
ObjectMapper
.Map<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>(Product.ProductDetail));
createDto.ProductDetailId = detail.Id;
}
var product = await _service.CreateAsync(createDto);
await _service.CreateAsync(createDto);
return NoContent();
}

49
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/EditModal.cshtml.cs

@ -59,8 +59,6 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
.Select(dto => new SelectListItem(dto.DisplayName, dto.Id.ToString())).ToList();
var productDto = await _service.GetAsync(Id);
var detailDto = await _productDetailAppService.GetAsync(productDto.ProductDetailId);
Product = ObjectMapper.Map<ProductDto, CreateEditProductViewModel>(productDto);
@ -70,26 +68,51 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
MaxResultCount = LimitedResultRequestDto.MaxMaxResultCount
})).Items.Select(x => x.CategoryId).ToList();
Product.ProductDetail = new CreateEditProductDetailViewModel
if (productDto.ProductDetailId.HasValue)
{
StoreId = detailDto.StoreId,
Description = detailDto.Description
};
var detailDto = await _productDetailAppService.GetAsync(productDto.ProductDetailId.Value);
Product.ProductDetail = new CreateEditProductDetailViewModel
{
StoreId = detailDto.StoreId,
Description = detailDto.Description
};
}
}
public virtual async Task<IActionResult> OnPostAsync()
{
var product = await _service.GetAsync(Id);
var originalProduct = await _service.GetAsync(Id);
var detail = await _productDetailAppService.GetAsync(product.ProductDetailId);
var updateProductDto = ObjectMapper.Map<CreateEditProductViewModel, CreateUpdateProductDto>(Product);
await _productDetailAppService.UpdateAsync(detail.Id,
ObjectMapper
.Map<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>(Product.ProductDetail));
if (Product.ProductDetail.HasContent())
{
if (originalProduct.ProductDetailId.HasValue)
{
var detail = await _productDetailAppService.GetAsync(originalProduct.ProductDetailId.Value);
var updateProductDto = ObjectMapper.Map<CreateEditProductViewModel, CreateUpdateProductDto>(Product);
await _productDetailAppService.UpdateAsync(detail.Id,
ObjectMapper.Map<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>(
Product.ProductDetail));
updateProductDto.ProductDetailId = detail.Id;
}
else
{
var detail = await _productDetailAppService.CreateAsync(
ObjectMapper.Map<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>(
Product.ProductDetail));
updateProductDto.ProductDetailId = detail.Id;
updateProductDto.ProductDetailId = detail.Id;
}
}
else if (originalProduct.ProductDetailId.HasValue)
{
await _productDetailAppService.DeleteAsync(originalProduct.ProductDetailId.Value);
updateProductDto.ProductDetailId = null;
}
await _service.UpdateAsync(Id, updateProductDto);
return NoContent();

5
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateEditProductDetailViewModel.cs

@ -18,5 +18,10 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewM
[TextArea(Rows = 4)]
[Display(Name = "ProductDetailDescription")]
public string Description { get; set; }
public bool HasContent()
{
return !Description.IsNullOrEmpty();
}
}
}

110
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Domain.Tests/Products/ProductDomainTests.cs

@ -1,4 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Xunit;
@ -6,18 +9,117 @@ namespace EasyAbp.EShop.Products.Products
{
public class ProductDomainTests : ProductsDomainTestBase
{
private IProductRepository ProductRepository { get; }
private IProductManager ProductManager { get; }
public ProductDomainTests()
{
ProductRepository = ServiceProvider.GetRequiredService<IProductRepository>();
ProductManager = ServiceProvider.GetRequiredService<IProductManager>();
}
[Fact]
public async Task Should_Set_ProductDetailId()
{
var product2 = new Product(ProductsTestData.Product2Id, null, ProductsTestData.Store1Id, "Default",
ProductsTestData.ProductDetails2Id, "Ball", "Ball", InventoryStrategy.NoNeed, true, false, false, null,
null, 0);
await ProductManager.CreateAsync(product2);
product2 = await ProductRepository.GetAsync(product2.Id);
product2.ProductDetailId.ShouldBe(ProductsTestData.ProductDetails2Id);
}
[Fact]
public async Task Should_Set_Sku_ProductDetailId()
{
await WithUnitOfWorkAsync(async () =>
{
var product1 = await ProductRepository.GetAsync(ProductsTestData.Product1Id);
var sku1 = product1.ProductSkus.Single(x => x.Id == ProductsTestData.Product1Sku1Id);
sku1.ProductDetailId.ShouldBeNull();
typeof(ProductSku).GetProperty(nameof(ProductSku.ProductDetailId))!.SetValue(sku1,
ProductsTestData.ProductDetails1Id);
await ProductManager.UpdateAsync(product1);
product1 = await ProductRepository.GetAsync(product1.Id);
sku1 = product1.ProductSkus.Single(x => x.Id == ProductsTestData.Product1Sku1Id);
sku1.ProductDetailId.ShouldBe(ProductsTestData.ProductDetails1Id);
});
}
[Fact]
public async Task Test1()
public async Task Should_Reuse_ProductDetail()
{
// Arrange
var product1 = await ProductRepository.GetAsync(ProductsTestData.Product1Id);
product1.ProductDetailId.ShouldBe(ProductsTestData.ProductDetails1Id);
var product2 = new Product(ProductsTestData.Product2Id, null, ProductsTestData.Store1Id, "Default",
ProductsTestData.ProductDetails2Id, "Ball", "Ball", InventoryStrategy.NoNeed, true, false, false, null,
null, 0);
await ProductManager.CreateAsync(product2);
product2 = await ProductRepository.GetAsync(product2.Id);
product2.ProductDetailId.ShouldBe(ProductsTestData.ProductDetails2Id);
typeof(Product).GetProperty(nameof(Product.ProductDetailId))!.SetValue(product2,
ProductsTestData.ProductDetails1Id);
await ProductManager.UpdateAsync(product2);
product2 = await ProductRepository.GetAsync(product2.Id);
product2.ProductDetailId.ShouldBe(ProductsTestData.ProductDetails1Id);
}
[Fact]
public async Task Should_Remove_ProductDetailId()
{
await Should_Set_ProductDetailId();
var product2 = await ProductRepository.GetAsync(ProductsTestData.Product2Id);
product2.ProductDetailId.ShouldNotBeNull();
typeof(Product).GetProperty(nameof(Product.ProductDetailId))!.SetValue(product2, null);
await ProductManager.UpdateAsync(product2);
product2 = await ProductRepository.GetAsync(product2.Id);
product2.ProductDetailId.ShouldBeNull();
}
[Fact]
public async Task Should_Remove_Sku_ProductDetailId()
{
await WithUnitOfWorkAsync(async () =>
{
await Should_Set_Sku_ProductDetailId();
var product1 = await ProductRepository.GetAsync(ProductsTestData.Product1Id);
var sku1 = product1.ProductSkus.Single(x => x.Id == ProductsTestData.Product1Sku1Id);
sku1.ProductDetailId.ShouldNotBeNull();
typeof(ProductSku).GetProperty(nameof(Product.ProductDetailId))!.SetValue(sku1, null);
await ProductManager.UpdateAsync(product1);
// Assert
product1 = await ProductRepository.GetAsync(product1.Id);
sku1 = product1.ProductSkus.Single(x => x.Id == ProductsTestData.Product1Sku1Id);
// Assert
sku1.ProductDetailId.ShouldBeNull();
});
}
}
}

2
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestData.cs

@ -12,6 +12,8 @@ namespace EasyAbp.EShop.Products
public static Guid Product1Id { get; } = Guid.NewGuid();
public static Guid Product2Id { get; } = Guid.NewGuid();
public static Guid Product1Attribute1Id { get; } = Guid.NewGuid();
public static Guid Product1Attribute1Option1Id { get; } = Guid.NewGuid();

5131
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/20220411111127_MadeProductDetailIdNullable.Designer.cs

File diff suppressed because it is too large

70
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/20220411111127_MadeProductDetailIdNullable.cs

@ -0,0 +1,70 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace EShopSample.Migrations
{
public partial class MadeProductDetailIdNullable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<Guid>(
name: "ProductDetailId",
table: "EasyAbpEShopProductsProductViews",
type: "uniqueidentifier",
nullable: true,
oldClrType: typeof(Guid),
oldType: "uniqueidentifier");
migrationBuilder.AlterColumn<Guid>(
name: "ProductDetailId",
table: "EasyAbpEShopProductsProducts",
type: "uniqueidentifier",
nullable: true,
oldClrType: typeof(Guid),
oldType: "uniqueidentifier");
migrationBuilder.AlterColumn<DateTime>(
name: "ProductDetailModificationTime",
table: "EasyAbpEShopOrdersOrderLines",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<Guid>(
name: "ProductDetailId",
table: "EasyAbpEShopProductsProductViews",
type: "uniqueidentifier",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
oldClrType: typeof(Guid),
oldType: "uniqueidentifier",
oldNullable: true);
migrationBuilder.AlterColumn<Guid>(
name: "ProductDetailId",
table: "EasyAbpEShopProductsProducts",
type: "uniqueidentifier",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
oldClrType: typeof(Guid),
oldType: "uniqueidentifier",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "ProductDetailModificationTime",
table: "EasyAbpEShopOrdersOrderLines",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
}
}
}

8
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/EShopSampleDbContextModelSnapshot.cs

@ -19,7 +19,7 @@ namespace EShopSample.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("ProductVersion", "6.0.2")
.HasAnnotation("ProductVersion", "6.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
@ -214,7 +214,7 @@ namespace EShopSample.Migrations
b.Property<Guid?>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("ProductDetailModificationTime")
b.Property<DateTime?>("ProductDetailModificationTime")
.HasColumnType("datetime2");
b.Property<string>("ProductDisplayName")
@ -1398,7 +1398,7 @@ namespace EShopSample.Migrations
b.Property<TimeSpan?>("PaymentExpireIn")
.HasColumnType("time");
b.Property<Guid>("ProductDetailId")
b.Property<Guid?>("ProductDetailId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ProductGroupName")
@ -1670,7 +1670,7 @@ namespace EShopSample.Migrations
b.Property<decimal?>("MinimumPrice")
.HasColumnType("decimal(20,8)");
b.Property<Guid>("ProductDetailId")
b.Property<Guid?>("ProductDetailId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ProductGroupDisplayName")

Loading…
Cancel
Save