Browse Source

Make Product entities belong to a store. #110

pull/112/head
gdlcf88 5 years ago
parent
commit
d5f62f8e56
  1. 2
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs
  2. 2
      modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs
  3. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissionDefinitionProvider.cs
  4. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissions.cs
  5. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/CreateUpdateProductDetailDto.cs
  6. 10
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/GetProductDetailListInput.cs
  7. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/ProductDetailDto.cs
  8. 3
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/IProductDetailAppService.cs
  9. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/UpdateProductInventoryDto.cs
  10. 12
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/CreateUpdateProductDto.cs
  11. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductDto.cs
  12. 3
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs
  13. 14
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/IProductAppService.cs
  14. 80
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductDetails/ProductDetailAppService.cs
  15. 27
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs
  16. 143
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
  17. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp.EShop.Products.Domain.Shared.csproj
  18. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/EShopProductsDomainSharedModule.cs
  19. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/cs.json
  20. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
  21. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pl.json
  22. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pt-BR.json
  23. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/sl.json
  24. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/tr.json
  25. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/vi.json
  26. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
  27. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
  28. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProduct.cs
  29. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/ProductEto.cs
  30. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp.EShop.Products.Domain.csproj
  31. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/EShopProductsDomainModule.cs
  32. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductDetails/ProductDetail.cs
  33. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductHistories/IProductHistoryRecorder.cs
  34. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductHistories/ProductHistoryRecorder.cs
  35. 12
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductStores/IProductStoreRepository.cs
  36. 33
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductStores/ProductStore.cs
  37. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductInventoryProvider.cs
  38. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductPriceProvider.cs
  39. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountProvider.cs
  40. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductInventoryProvider.cs
  41. 12
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductManager.cs
  42. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductPriceProvider.cs
  43. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductRepository.cs
  44. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderCreatedEventHandler.cs
  45. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderPaidEventHandler.cs
  46. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/Product.cs
  47. 43
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs
  48. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductSku.cs
  49. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/EShopProductsEntityFrameworkCoreModule.cs
  50. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/IProductsDbContext.cs
  51. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs
  52. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs
  53. 29
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/ProductStores/ProductStoreRepository.cs
  54. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/DuplicatedProductUniqueNameException.cs
  55. 52
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/ProductRepository.cs
  56. 10
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/ProductDetails/ProductDetailController.cs
  57. 40
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/Products/ProductController.cs
  58. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/EasyAbp.EShop.Products.Web.csproj
  59. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Menus/ProductsMenuContributor.cs
  60. 19
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/CreateModal.cshtml.cs
  61. 19
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/EditModal.cshtml.cs
  62. 87
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml
  63. 28
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml.cs
  64. 10
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateProductDetailViewModel.cs
  65. 74
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateProductViewModel.cs
  66. 12
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/EditProductDetailViewModel.cs
  67. 11
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/EditProductViewModel.cs
  68. 28
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/ProductListFilterViewModel.cs
  69. 14
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/index.js
  70. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ChangeInventoryModal.cshtml
  71. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ChangeInventoryModal.cshtml.cs
  72. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/CreateModal.cshtml
  73. 9
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/CreateModal.cshtml.cs
  74. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/EditModal.cshtml
  75. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/EditModal.cshtml.cs
  76. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/Index.cshtml
  77. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/Index.cshtml.cs
  78. 10
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/index.js
  79. 29
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/ProductsWebAutoMapperProfile.cs
  80. 2
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductAppServiceTests.cs
  81. 23
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Domain.Tests/ProductStores/ProductStoreDomainTests.cs
  82. 31
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductStores/ProductStoreRepositoryTests.cs
  83. 3
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestDataBuilder.cs
  84. 2
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/StoreOwnerDto.cs
  85. 13
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Stores/Dtos/GetStoreListInput.cs
  86. 2
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Stores/IStoreAppService.cs
  87. 1
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp.EShop.Stores.Application.csproj
  88. 4
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/EShopStoresApplicationModule.cs
  89. 42
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerAppService.cs
  90. 43
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/StoreAppService.cs
  91. 4
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoresApplicationAutoMapperProfile.cs
  92. 6
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain.Shared/EasyAbp/EShop/Stores/StoresConsts.cs
  93. 3
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/Stores/IStoreRepository.cs
  94. 11
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/Stores/StoreRepository.cs
  95. 4
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.HttpApi/EasyAbp/EShop/Stores/Stores/StoreController.cs
  96. 8
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EShopStoresWebModule.cs
  97. 1
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EasyAbp.EShop.Stores.Web.csproj
  98. 12
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/Index.js
  99. 17
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/ViewModels/CreateStoreOwnerViewModel.cs
  100. 2
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs

2
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs

@ -120,7 +120,7 @@ namespace EasyAbp.EShop.Orders.Orders
foreach (var productId in productIds.Distinct().ToList())
{
dict.Add(productId, await _productAppService.GetAsync(productId, storeId));
dict.Add(productId, await _productAppService.GetAsync(productId));
}
return dict;

2
modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs

@ -25,7 +25,7 @@ namespace EasyAbp.EShop.Orders.Orders
protected override void AfterAddApplication(IServiceCollection services)
{
var productAppService = Substitute.For<IProductAppService>();
productAppService.GetAsync(OrderTestData.Product1Id, OrderTestData.Store1Id).Returns(Task.FromResult(new ProductDto
productAppService.GetAsync(OrderTestData.Product1Id).Returns(Task.FromResult(new ProductDto
{
CreationTime = DateTime.Now,
IsPublished = true,

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissionDefinitionProvider.cs

@ -13,6 +13,7 @@ namespace EasyAbp.EShop.Products.Permissions
var categories = moduleGroup.AddPermission(ProductsPermissions.Categories.Default, L("Permission:Category"));
categories.AddChild(ProductsPermissions.Categories.CrossStore, L("Permission:CrossStore"));
categories.AddChild(ProductsPermissions.Categories.Manage, L("Permission:Manage"));
categories.AddChild(ProductsPermissions.Categories.Create, L("Permission:Create"));
categories.AddChild(ProductsPermissions.Categories.Update, L("Permission:Update"));
categories.AddChild(ProductsPermissions.Categories.Delete, L("Permission:Delete"));
@ -20,6 +21,7 @@ namespace EasyAbp.EShop.Products.Permissions
var product = moduleGroup.AddPermission(ProductsPermissions.Products.Default, L("Permission:Product"));
product.AddChild(ProductsPermissions.Products.CrossStore, L("Permission:CrossStore"));
product.AddChild(ProductsPermissions.Products.Manage, L("Permission:Manage"));
product.AddChild(ProductsPermissions.Products.Create, L("Permission:Create"));
product.AddChild(ProductsPermissions.Products.Update, L("Permission:Update"));
product.AddChild(ProductsPermissions.Products.Delete, L("Permission:Delete"));

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissions.cs

@ -10,6 +10,7 @@ namespace EasyAbp.EShop.Products.Permissions
{
public const string Default = GroupName + ".Category";
public const string CrossStore = Default + ".CrossStore";
public const string Manage = Default + ".Manage";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
@ -20,6 +21,7 @@ namespace EasyAbp.EShop.Products.Permissions
{
public const string Default = GroupName + ".Product";
public const string CrossStore = Default + ".CrossStore";
public const string Manage = Default + ".Manage";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";

5
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/CreateUpdateProductDetailDto.cs

@ -7,11 +7,8 @@ namespace EasyAbp.EShop.Products.ProductDetails.Dtos
[Serializable]
public class CreateUpdateProductDetailDto : ExtensibleObject
{
/// <summary>
/// This property is for product management permission checking
/// </summary>
[DisplayName("ProductDetailStoreId")]
public Guid StoreId { get; set; }
public Guid? StoreId { get; set; }
[DisplayName("ProductDetailDescription")]
public string Description { get; set; }

10
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/Dtos/GetProductDetailListInput.cs

@ -0,0 +1,10 @@
using System;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Products.ProductDetails.Dtos
{
public class GetProductDetailListInput : PagedAndSortedResultRequestDto
{
public Guid? StoreId { get; set; }
}
}

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

@ -6,6 +6,8 @@ namespace EasyAbp.EShop.Products.ProductDetails.Dtos
[Serializable]
public class ProductDetailDto : ExtensibleEntityDto<Guid>
{
public Guid? StoreId { get; set; }
public string Description { get; set; }
}
}

3
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductDetails/IProductDetailAppService.cs

@ -10,10 +10,9 @@ namespace EasyAbp.EShop.Products.ProductDetails
ICrudAppService<
ProductDetailDto,
Guid,
PagedAndSortedResultRequestDto,
GetProductDetailListInput,
CreateUpdateProductDetailDto,
CreateUpdateProductDetailDto>
{
Task DeleteAsync(Guid id, Guid storeId);
}
}

4
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/UpdateProductInventoryDto.cs

@ -9,9 +9,7 @@ namespace EasyAbp.EShop.Products.ProductInventories.Dtos
public Guid ProductId { get; set; }
public Guid ProductSkuId { get; set; }
public Guid? StoreId { get; set; }
/// <summary>
/// Reduce inventory if the value is less than 0
/// </summary>

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

@ -3,24 +3,22 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using EasyAbp.EShop.Stores.Stores;
using Volo.Abp.ObjectExtending;
namespace EasyAbp.EShop.Products.Products.Dtos
{
[Serializable]
public class CreateUpdateProductDto : ExtensibleObject
public class CreateUpdateProductDto : ExtensibleObject, IMultiStore
{
[DisplayName("ProductStoreId")]
public Guid StoreId { get; set; }
[DisplayName("ProductProductGroupName")]
public string ProductGroupName { get; set; }
[DisplayName("ProductDetailId")]
public Guid ProductDetailId { get; set; }
/// <summary>
/// This property is set for adding the store to ProductStore in creation, or for permission checking in update.
/// </summary>
[DisplayName("ProductStoreId")]
public Guid StoreId { 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

@ -8,6 +8,8 @@ namespace EasyAbp.EShop.Products.Products.Dtos
[Serializable]
public class ProductDto : ExtensibleFullAuditedEntityDto<Guid>
{
public Guid StoreId { get; set; }
public string ProductGroupName { get; set; }
public string ProductGroupDisplayName { get; set; }

3
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs

@ -16,9 +16,6 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public decimal? OriginalPrice { get; set; }
/// <summary>
/// Price property in the ProductSku entity.
/// </summary>
public decimal Price { get; set; }
public decimal DiscountedPrice { get; set; }

14
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/IProductAppService.cs

@ -14,17 +14,13 @@ namespace EasyAbp.EShop.Products.Products
CreateUpdateProductDto,
CreateUpdateProductDto>
{
Task DeleteAsync(Guid id, Guid storeId);
Task<ProductDto> CreateSkuAsync(Guid productId, CreateProductSkuDto input);
Task<ProductDto> CreateSkuAsync(Guid productId, Guid storeId, CreateProductSkuDto input);
Task<ProductDto> UpdateSkuAsync(Guid productId, Guid productSkuId, UpdateProductSkuDto input);
Task<ProductDto> UpdateSkuAsync(Guid productId, Guid productSkuId, Guid storeId, UpdateProductSkuDto input);
Task<ProductDto> GetAsync(Guid id, Guid storeId);
Task<ProductDto> GetByCodeAsync(string code, Guid storeId);
Task<ProductDto> DeleteSkuAsync(Guid productId, Guid productSkuId, Guid storeId);
Task<ProductDto> DeleteSkuAsync(Guid productId, Guid productSkuId);
Task<ProductDto> GetByCodeAsync(Guid storeId, string code);
Task<ListResultDto<ProductGroupDto>> GetProductGroupListAsync();
}

80
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductDetails/ProductDetailAppService.cs

@ -1,16 +1,16 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.ProductStores;
using Volo.Abp;
using EasyAbp.EShop.Stores.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace EasyAbp.EShop.Products.ProductDetails
{
public class ProductDetailAppService : CrudAppService<ProductDetail, ProductDetailDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateProductDetailDto, CreateUpdateProductDetailDto>,
public class ProductDetailAppService : CrudAppService<ProductDetail, ProductDetailDto, Guid, GetProductDetailListInput, CreateUpdateProductDetailDto, CreateUpdateProductDetailDto>,
IProductDetailAppService
{
protected override string CreatePolicyName { get; set; } = ProductsPermissions.Products.Create;
@ -20,26 +20,70 @@ namespace EasyAbp.EShop.Products.ProductDetails
protected override string GetListPolicyName { get; set; } = ProductsPermissions.Products.Default;
private readonly IProductRepository _productRepository;
private readonly IProductStoreRepository _productStoreRepository;
private readonly IProductDetailRepository _repository;
public ProductDetailAppService(
IProductRepository productRepository,
IProductStoreRepository productStoreRepository,
IProductDetailRepository repository) : base(repository)
{
_productRepository = productRepository;
_productStoreRepository = productStoreRepository;
_repository = repository;
}
protected override IQueryable<ProductDetail> CreateFilteredQuery(GetProductDetailListInput input)
{
return _repository.WhereIf(input.StoreId.HasValue, x => x.StoreId == input.StoreId.Value);
}
public override async Task<PagedResultDto<ProductDetailDto>> GetListAsync(GetProductDetailListInput input)
{
await AuthorizationService.CheckMultiStorePolicyAsync(input.StoreId, GetListPolicyName,
ProductsPermissions.Products.CrossStore);
var query = CreateFilteredQuery(input);
var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
var productDetails = await AsyncExecuter.ToListAsync(query);
var entityDtos = await MapToGetListOutputDtosAsync(productDetails);
return new PagedResultDto<ProductDetailDto>(
totalCount,
entityDtos
);
}
public override async Task<ProductDetailDto> CreateAsync(CreateUpdateProductDetailDto input)
{
await AuthorizationService.CheckMultiStorePolicyAsync(input.StoreId, CreatePolicyName,
ProductsPermissions.Products.CrossStore);
var productDetail = await MapToEntityAsync(input);
TryToSetTenantId(productDetail);
await Repository.InsertAsync(productDetail, autoSave: true);
return await MapToGetOutputDtoAsync(productDetail);
}
public override async Task<ProductDetailDto> UpdateAsync(Guid id, CreateUpdateProductDetailDto input)
{
await CheckUpdatePolicyAsync();
var product = await _productRepository.GetAsync(x => x.ProductDetailId == id);
await AuthorizationService.CheckMultiStorePolicyAsync(product.StoreId, UpdatePolicyName,
ProductsPermissions.Products.CrossStore);
await CheckStoreIsProductOwnerAsync(product.Id, input.StoreId);
if (input.StoreId != product.StoreId)
{
await AuthorizationService.CheckMultiStorePolicyAsync(input.StoreId, UpdatePolicyName,
ProductsPermissions.Products.CrossStore);
}
var detail = await GetEntityByIdAsync(id);
@ -50,32 +94,16 @@ namespace EasyAbp.EShop.Products.ProductDetails
return await MapToGetOutputDtoAsync(detail);
}
public virtual async Task DeleteAsync(Guid id, Guid storeId)
public override async Task DeleteAsync(Guid id)
{
await CheckDeletePolicyAsync();
var product = await _productRepository.GetAsync(x => x.ProductDetailId == id);
await CheckStoreIsProductOwnerAsync(product.Id, storeId);
await AuthorizationService.CheckMultiStorePolicyAsync(product.StoreId, DeletePolicyName,
ProductsPermissions.Products.CrossStore);
await Repository.DeleteAsync(id);
}
[Obsolete("Should use DeleteAsync(Guid id, Guid storeId)")]
[RemoteService(false)]
public override Task DeleteAsync(Guid id)
{
throw new NotSupportedException();
}
protected virtual async Task CheckStoreIsProductOwnerAsync(Guid productId, Guid storeId)
{
var productStore = await _productStoreRepository.GetAsync(productId, storeId);
if (!productStore.IsOwner)
{
throw new StoreIsNotProductOwnerException(productId, storeId);
}
}
}
}

27
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs

@ -1,29 +1,27 @@
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.ProductStores;
using EasyAbp.EShop.Stores.Authorization;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Validation;
namespace EasyAbp.EShop.Products.ProductInventories
{
public class ProductInventoryAppService : ApplicationService, IProductInventoryAppService
{
private readonly IProductRepository _productRepository;
private readonly IProductInventoryRepository _repository;
private readonly IProductStoreRepository _productStoreRepository;
private readonly DefaultProductInventoryProvider _productInventoryProvider;
public ProductInventoryAppService(
IProductRepository productRepository,
IProductInventoryRepository repository,
IProductStoreRepository productStoreRepository,
DefaultProductInventoryProvider productInventoryProvider)
{
_productRepository = productRepository;
_repository = repository;
_productStoreRepository = productStoreRepository;
_productInventoryProvider = productInventoryProvider;
}
@ -44,13 +42,10 @@ namespace EasyAbp.EShop.Products.ProductInventories
public virtual async Task<ProductInventoryDto> UpdateAsync(UpdateProductInventoryDto input)
{
await AuthorizationService.CheckMultiStorePolicyAsync(input.StoreId,
ProductsPermissions.ProductInventory.Update, ProductsPermissions.ProductInventory.CrossStore);
var product = await _productRepository.GetAsync(input.ProductId);
if (input.StoreId.HasValue)
{
await CheckStoreIsProductOwnerAsync(input.ProductId, input.StoreId.Value);
}
await AuthorizationService.CheckMultiStorePolicyAsync(product.StoreId,
ProductsPermissions.ProductInventory.Update, ProductsPermissions.ProductInventory.CrossStore);
var productInventory = await _repository.FindAsync(x => x.ProductSkuId == input.ProductSkuId);
@ -66,16 +61,6 @@ namespace EasyAbp.EShop.Products.ProductInventories
return ObjectMapper.Map<ProductInventory, ProductInventoryDto>(productInventory);
}
protected virtual async Task CheckStoreIsProductOwnerAsync(Guid productId, Guid storeId)
{
var productStore = await _productStoreRepository.GetAsync(productId, storeId);
if (!productStore.IsOwner)
{
throw new StoreIsNotProductOwnerException(productId, storeId);
}
}
protected virtual async Task ChangeInventoryAsync(ProductInventory productInventory, int changedInventory)
{

143
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs

@ -1,35 +1,31 @@
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.Products.Dtos;
using EasyAbp.EShop.Products.ProductStores;
using EasyAbp.EShop.Stores.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Options;
using EasyAbp.EShop.Stores.Stores;
using Microsoft.Extensions.Options;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
namespace EasyAbp.EShop.Products.Products
{
public class ProductAppService : CrudAppService<Product, ProductDto, Guid, GetProductListDto, CreateUpdateProductDto
, CreateUpdateProductDto>,
IProductAppService
public class ProductAppService : MultiStoreCrudAppService<Product, ProductDto, Guid, GetProductListDto, CreateUpdateProductDto, CreateUpdateProductDto>, IProductAppService
{
protected override string CreatePolicyName { get; set; } = ProductsPermissions.Products.Create;
protected override string DeletePolicyName { get; set; } = ProductsPermissions.Products.Delete;
protected override string UpdatePolicyName { get; set; } = ProductsPermissions.Products.Update;
protected override string GetPolicyName { get; set; } = null;
protected override string GetListPolicyName { get; set; } = null;
protected override string CrossStorePolicyName { get; set; } = ProductsPermissions.Products.CrossStore;
private readonly IProductManager _productManager;
private readonly EShopProductsOptions _options;
private readonly IProductInventoryProvider _productInventoryProvider;
private readonly IAttributeOptionIdsSerializer _attributeOptionIdsSerializer;
private readonly IProductStoreRepository _productStoreRepository;
private readonly IProductRepository _repository;
public ProductAppService(
@ -37,22 +33,24 @@ namespace EasyAbp.EShop.Products.Products
IOptions<EShopProductsOptions> options,
IProductInventoryProvider productInventoryProvider,
IAttributeOptionIdsSerializer attributeOptionIdsSerializer,
IProductStoreRepository productStoreRepository,
IProductRepository repository) : base(repository)
{
_productManager = productManager;
_options = options.Value;
_productInventoryProvider = productInventoryProvider;
_attributeOptionIdsSerializer = attributeOptionIdsSerializer;
_productStoreRepository = productStoreRepository;
_repository = repository;
}
protected override IQueryable<Product> CreateFilteredQuery(GetProductListDto input)
{
var query = _repository.WithDetails(input.StoreId, input.CategoryId);
var query = input.CategoryId.HasValue
? _repository.WithDetails(input.CategoryId.Value)
: _repository.WithDetails();
return input.ShowHidden ? query : query.Where(x => !x.IsHidden);
return query
.Where(x => x.StoreId == input.StoreId)
.WhereIf(!input.ShowHidden, x => !x.IsHidden);
}
protected override Product MapToEntity(CreateUpdateProductDto createInput)
@ -64,20 +62,19 @@ namespace EasyAbp.EShop.Products.Products
public override async Task<ProductDto> CreateAsync(CreateUpdateProductDto input)
{
await AuthorizationService.CheckMultiStorePolicyAsync(input.StoreId, CreatePolicyName,
ProductsPermissions.Products.CrossStore);
var product = MapToEntity(input);
await CheckMultiStorePolicyAsync(product.StoreId, CreatePolicyName);
TryToSetTenantId(product);
await UpdateProductAttributesAsync(product, input);
await _productManager.CreateAsync(product, input.StoreId, input.CategoryIds);
await _productManager.CreateAsync(product, input.CategoryIds);
var dto = await MapToGetOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, dto, input.StoreId);
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
return dto;
@ -85,13 +82,15 @@ namespace EasyAbp.EShop.Products.Products
public override async Task<ProductDto> UpdateAsync(Guid id, CreateUpdateProductDto input)
{
await AuthorizationService.CheckMultiStorePolicyAsync(input.StoreId, UpdatePolicyName,
ProductsPermissions.Products.CrossStore);
await CheckStoreIsProductOwnerAsync(id, input.StoreId);
var product = await GetEntityByIdAsync(id);
await CheckMultiStorePolicyAsync(product.StoreId, UpdatePolicyName);
if (input.StoreId != product.StoreId)
{
await CheckMultiStorePolicyAsync(input.StoreId, UpdatePolicyName);
}
CheckProductIsNotStatic(product);
MapToEntity(input, product);
@ -102,22 +101,12 @@ namespace EasyAbp.EShop.Products.Products
var dto = await MapToGetOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, dto, input.StoreId);
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
return dto;
}
protected virtual async Task CheckStoreIsProductOwnerAsync(Guid productId, Guid storeId)
{
var productStore = await _productStoreRepository.GetAsync(productId, storeId);
if (!productStore.IsOwner)
{
throw new StoreIsNotProductOwnerException(productId, storeId);
}
}
protected virtual async Task UpdateProductAttributesAsync(Product product, CreateUpdateProductDto input)
{
var isProductSkusEmpty = product.ProductSkus.IsNullOrEmpty();
@ -191,21 +180,7 @@ namespace EasyAbp.EShop.Products.Products
product.ProductAttributes.RemoveAll(a => removedAttributeNames.Contains(a.DisplayName));
}
[Obsolete("Should use DeleteAsync(Guid id, Guid storeId)")]
[RemoteService(false)]
public override Task DeleteAsync(Guid id)
{
throw new NotSupportedException();
}
[Obsolete("Should use GetAsync(Guid id, Guid storeId)")]
[RemoteService(false)]
public override Task<ProductDto> GetAsync(Guid id)
{
throw new NotSupportedException();
}
public virtual async Task<ProductDto> GetAsync(Guid id, Guid storeId)
public override async Task<ProductDto> GetAsync(Guid id)
{
await CheckGetPolicyAsync();
@ -213,12 +188,12 @@ namespace EasyAbp.EShop.Products.Products
if (!product.IsPublished)
{
await CheckStoreIsProductOwnerAsync(product.Id, storeId);
await CheckMultiStorePolicyAsync(product.StoreId, ProductsPermissions.Products.Manage);
}
var dto = await MapToGetOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, dto, storeId);
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
return dto;
@ -236,7 +211,7 @@ namespace EasyAbp.EShop.Products.Products
return Task.CompletedTask;
}
public virtual async Task<ProductDto> GetByCodeAsync(string code, Guid storeId)
public virtual async Task<ProductDto> GetByCodeAsync(Guid storeId, string code)
{
await CheckGetPolicyAsync();
@ -244,12 +219,12 @@ namespace EasyAbp.EShop.Products.Products
if (!product.IsPublished)
{
await CheckStoreIsProductOwnerAsync(product.Id, storeId);
await CheckMultiStorePolicyAsync(product.StoreId, ProductsPermissions.Products.Manage);
}
var dto = await MapToGetOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, dto, storeId);
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
return dto;
@ -289,7 +264,7 @@ namespace EasyAbp.EShop.Products.Products
{
var productDto = await MapToGetListOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, productDto, input.StoreId);
await LoadDtoExtraDataAsync(product, productDto);
items.Add(productDto);
}
@ -299,10 +274,9 @@ namespace EasyAbp.EShop.Products.Products
return new PagedResultDto<ProductDto>(totalCount, items);
}
protected virtual async Task<ProductDto> LoadDtoInventoryDataAsync(Product product, ProductDto productDto,
Guid storeId)
protected virtual async Task<ProductDto> LoadDtoInventoryDataAsync(Product product, ProductDto productDto)
{
var inventoryDataDict = await _productInventoryProvider.GetInventoryDataDictionaryAsync(product, storeId);
var inventoryDataDict = await _productInventoryProvider.GetInventoryDataDictionaryAsync(product);
productDto.Sold = 0;
@ -318,21 +292,21 @@ namespace EasyAbp.EShop.Products.Products
return productDto;
}
protected virtual async Task<ProductDto> LoadDtoExtraDataAsync(Product product, ProductDto productDto, Guid storeId)
protected virtual async Task<ProductDto> LoadDtoExtraDataAsync(Product product, ProductDto productDto)
{
await LoadDtoInventoryDataAsync(product, productDto, storeId);
await LoadDtoPriceDataAsync(product, productDto, storeId);
await LoadDtoInventoryDataAsync(product, productDto);
await LoadDtoPriceDataAsync(product, productDto);
return productDto;
}
protected virtual async Task<ProductDto> LoadDtoPriceDataAsync(Product product, ProductDto productDto, Guid storeId)
protected virtual async Task<ProductDto> LoadDtoPriceDataAsync(Product product, ProductDto productDto)
{
foreach (var productSku in product.ProductSkus)
{
var productSkuDto = productDto.ProductSkus.First(x => x.Id == productSku.Id);
var priceDataModel = await _productManager.GetProductPriceAsync(product, productSku, storeId);
var priceDataModel = await _productManager.GetProductPriceAsync(product, productSku);
productSkuDto.Price = priceDataModel.Price;
productSkuDto.DiscountedPrice = priceDataModel.DiscountedPrice;
@ -347,17 +321,14 @@ namespace EasyAbp.EShop.Products.Products
return productDto;
}
public async Task DeleteAsync(Guid id, Guid storeId)
public override async Task DeleteAsync(Guid id)
{
await AuthorizationService.CheckMultiStorePolicyAsync(storeId, DeletePolicyName,
ProductsPermissions.Products.CrossStore);
var product = await GetEntityByIdAsync(id);
await CheckMultiStorePolicyAsync(product.StoreId, DeletePolicyName);
CheckProductIsNotStatic(product);
await CheckStoreIsProductOwnerAsync(id, storeId);
await _productManager.DeleteAsync(product);
}
@ -369,15 +340,12 @@ namespace EasyAbp.EShop.Products.Products
}
}
public async Task<ProductDto> CreateSkuAsync(Guid productId, Guid storeId, CreateProductSkuDto input)
public async Task<ProductDto> CreateSkuAsync(Guid productId, CreateProductSkuDto input)
{
await AuthorizationService.CheckMultiStorePolicyAsync(storeId, UpdatePolicyName,
ProductsPermissions.Products.CrossStore);
await CheckStoreIsProductOwnerAsync(productId, storeId);
var product = await GetEntityByIdAsync(productId);
await CheckMultiStorePolicyAsync(product.StoreId, UpdatePolicyName);
CheckProductIsNotStatic(product);
var sku = ObjectMapper.Map<CreateProductSkuDto, ProductSku>(input);
@ -388,22 +356,18 @@ namespace EasyAbp.EShop.Products.Products
var dto = await MapToGetOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, dto, storeId);
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
return dto;
}
public async Task<ProductDto> UpdateSkuAsync(Guid productId, Guid productSkuId, Guid storeId,
UpdateProductSkuDto input)
public async Task<ProductDto> UpdateSkuAsync(Guid productId, Guid productSkuId, UpdateProductSkuDto input)
{
await AuthorizationService.CheckMultiStorePolicyAsync(storeId, UpdatePolicyName,
ProductsPermissions.Products.CrossStore);
await CheckStoreIsProductOwnerAsync(productId, storeId);
var product = await GetEntityByIdAsync(productId);
await CheckMultiStorePolicyAsync(product.StoreId, UpdatePolicyName);
CheckProductIsNotStatic(product);
var sku = product.ProductSkus.Single(x => x.Id == productSkuId);
@ -414,21 +378,18 @@ namespace EasyAbp.EShop.Products.Products
var dto = await MapToGetOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, dto, storeId);
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
return dto;
}
public async Task<ProductDto> DeleteSkuAsync(Guid productId, Guid productSkuId, Guid storeId)
public async Task<ProductDto> DeleteSkuAsync(Guid productId, Guid productSkuId)
{
await AuthorizationService.CheckMultiStorePolicyAsync(storeId, UpdatePolicyName,
ProductsPermissions.Products.CrossStore);
await CheckStoreIsProductOwnerAsync(productId, storeId);
var product = await GetEntityByIdAsync(productId);
await CheckMultiStorePolicyAsync(product.StoreId, UpdatePolicyName);
CheckProductIsNotStatic(product);
var sku = product.ProductSkus.Single(x => x.Id == productSkuId);
@ -437,7 +398,7 @@ namespace EasyAbp.EShop.Products.Products
var dto = await MapToGetOutputDtoAsync(product);
await LoadDtoExtraDataAsync(product, dto, storeId);
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
return dto;

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp.EShop.Products.Domain.Shared.csproj

@ -11,6 +11,7 @@
<ItemGroup>
<PackageReference Include="EasyAbp.Abp.Trees.Domain.Shared" Version="1.4.0" />
<PackageReference Include="Volo.Abp.Validation" Version="$(AbpVersion)" />
<ProjectReference Include="..\..\..\EasyAbp.EShop.Stores\src\EasyAbp.EShop.Stores.Domain.Shared\EasyAbp.EShop.Stores.Domain.Shared.csproj" />
</ItemGroup>
<ItemGroup>

4
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/EShopProductsDomainSharedModule.cs

@ -2,6 +2,7 @@
using Volo.Abp.Modularity;
using Volo.Abp.Localization;
using EasyAbp.EShop.Products.Localization;
using EasyAbp.EShop.Stores;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Validation;
using Volo.Abp.Validation.Localization;
@ -11,7 +12,8 @@ namespace EasyAbp.EShop.Products
{
[DependsOn(
typeof(AbpValidationModule),
typeof(AbpTreesDomainSharedModule)
typeof(AbpTreesDomainSharedModule),
typeof(EShopStoresDomainSharedModule)
)]
public class EShopProductsDomainSharedModule : AbpModule
{

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

@ -5,7 +5,8 @@
"Menu:ProductManagement": "Products",
"Menu:Product": "Product",
"Product": "Product",
"ProductStore": "Store product",
"ProductStoreId": "Store ID",
"ProductCategoryId": "Category ID",
"ProductProductGroupName": "Product group name",
"ProductProductGroupDisplayName": "Product group",
"ProductDetailId": "Product detail ID",
@ -13,10 +14,8 @@
"ProductDisplayName": "Display name",
"ProductDisplayOrder": "Display order",
"ProductSold": "Sold",
"ProductDetailProductId": "Product detail ID",
"ProductDetailProductSkuId": "Product SKU ID",
"ProductDetailStoreId": "Store ID",
"ProductDetailDescription": "Description",
"ProductDetailDisplayOrder": "Display order",
"ProductCategory": "Categories",
"ProductAttribute": "Attribute",
"ProductAttributeNames": "Attribute names",

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

@ -6,7 +6,8 @@
"ManageYourProfile": "Manage your profile",
"Menu:Product": "Product",
"Product": "Product",
"ProductStore": "Store product",
"ProductStoreId": "Store ID",
"ProductCategoryId": "Category ID",
"ProductProductGroupName": "Product group name",
"ProductProductGroupDisplayName": "Product group",
"ProductDetailId": "Product detail ID",
@ -14,10 +15,8 @@
"ProductDisplayName": "Display name",
"ProductDisplayOrder": "Display order",
"ProductSold": "Sold",
"ProductDetailProductId": "Product detail ID",
"ProductDetailProductSkuId": "Product SKU ID",
"ProductDetailStoreId": "Store ID",
"ProductDetailDescription": "Description",
"ProductDetailDisplayOrder": "Display order",
"ProductCategory": "Categories",
"ProductAttribute": "Attribute",
"ProductAttributeNames": "Attribute names",

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

@ -5,7 +5,8 @@
"Menu:ProductManagement": "Products",
"Menu:Product": "Product",
"Product": "Product",
"ProductStore": "Store product",
"ProductStoreId": "Store ID",
"ProductCategoryId": "Category ID",
"ProductProductGroupName": "Product group name",
"ProductProductGroupDisplayName": "Product group",
"ProductDetailId": "Product detail ID",
@ -13,10 +14,8 @@
"ProductDisplayName": "Display name",
"ProductDisplayOrder": "Display order",
"ProductSold": "Sold",
"ProductDetailProductId": "Product detail ID",
"ProductDetailProductSkuId": "Product SKU ID",
"ProductDetailStoreId": "Store ID",
"ProductDetailDescription": "Description",
"ProductDetailDisplayOrder": "Display order",
"ProductCategory": "Categories",
"ProductAttribute": "Attribute",
"ProductAttributeNames": "Attribute names",

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

@ -5,7 +5,8 @@
"Menu:ProductManagement": "Products",
"Menu:Product": "Product",
"Product": "Product",
"ProductStore": "Store product",
"ProductStoreId": "Store ID",
"ProductCategoryId": "Category ID",
"ProductProductGroupName": "Product group name",
"ProductProductGroupDisplayName": "Product group",
"ProductDetailId": "Product detail ID",
@ -13,10 +14,8 @@
"ProductDisplayName": "Display name",
"ProductDisplayOrder": "Display order",
"ProductSold": "Sold",
"ProductDetailProductId": "Product detail ID",
"ProductDetailProductSkuId": "Product SKU ID",
"ProductDetailStoreId": "Store ID",
"ProductDetailDescription": "Description",
"ProductDetailDisplayOrder": "Display order",
"ProductCategory": "Categories",
"ProductAttribute": "Attribute",
"ProductAttributeNames": "Attribute names",

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

@ -6,7 +6,8 @@
"ManageYourProfile": "Upravljajte svojim profilom",
"Menu:Product": "Product",
"Product": "Product",
"ProductStore": "Store product",
"ProductStoreId": "Store ID",
"ProductCategoryId": "Category ID",
"ProductProductGroupName": "Product group name",
"ProductProductGroupDisplayName": "Product group",
"ProductDetailId": "Product detail ID",
@ -14,10 +15,8 @@
"ProductDisplayName": "Display name",
"ProductDisplayOrder": "Display order",
"ProductSold": "Sold",
"ProductDetailProductId": "Product detail ID",
"ProductDetailProductSkuId": "Product SKU ID",
"ProductDetailStoreId": "Store ID",
"ProductDetailDescription": "Description",
"ProductDetailDisplayOrder": "Display order",
"ProductCategory": "Categories",
"ProductAttribute": "Attribute",
"ProductAttributeNames": "Attribute names",

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

@ -6,7 +6,8 @@
"ManageYourProfile": "Profil y�netimi",
"Menu:Product": "Product",
"Product": "Product",
"ProductStore": "Store product",
"ProductStoreId": "Store ID",
"ProductCategoryId": "Category ID",
"ProductProductGroupName": "Product group name",
"ProductProductGroupDisplayName": "Product group",
"ProductDetailId": "Product detail ID",
@ -14,10 +15,8 @@
"ProductDisplayName": "Display name",
"ProductDisplayOrder": "Display order",
"ProductSold": "Sold",
"ProductDetailProductId": "Product detail ID",
"ProductDetailProductSkuId": "Product SKU ID",
"ProductDetailStoreId": "Store ID",
"ProductDetailDescription": "Description",
"ProductDetailDisplayOrder": "Display order",
"ProductCategory": "Categories",
"ProductAttribute": "Attribute",
"ProductAttributeNames": "Attribute names",

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

@ -5,7 +5,8 @@
"Menu:ProductManagement": "Products",
"Menu:Product": "Product",
"Product": "Product",
"ProductStore": "Store product",
"ProductStoreId": "Store ID",
"ProductCategoryId": "Category ID",
"ProductProductGroupName": "Product group name",
"ProductProductGroupDisplayName": "Product group",
"ProductDetailId": "Product detail ID",
@ -13,10 +14,8 @@
"ProductDisplayName": "Display name",
"ProductDisplayOrder": "Display order",
"ProductSold": "Sold",
"ProductDetailProductId": "Product detail ID",
"ProductDetailProductSkuId": "Product SKU ID",
"ProductDetailStoreId": "Store ID",
"ProductDetailDescription": "Description",
"ProductDetailDisplayOrder": "Display order",
"ProductCategory": "Categories",
"ProductAttribute": "Attribute",
"ProductAttributeNames": "Attribute names",

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

@ -6,7 +6,8 @@
"ManageYourProfile": "管理个人资料",
"Menu:Product": "商品",
"Product": "商品",
"ProductStore": "店铺商品",
"ProductStoreId": "店铺 ID",
"ProductCategoryId": "类目 ID",
"ProductProductGroupName": "商品组",
"ProductProductGroupDisplayName": "商品组名称",
"ProductDetailId": "商品详情 ID",
@ -14,10 +15,8 @@
"ProductDisplayName": "商品名称",
"ProductDisplayOrder": "展示顺序",
"ProductSold": "已售",
"ProductDetailProductId": "商品 ID",
"ProductDetailProductSkuId": "商品 SKU ID",
"ProductDetailStoreId": "店铺 ID",
"ProductDetailDescription": "内容",
"ProductDetailDisplayOrder": "展示顺序",
"ProductCategory": "所属类目",
"ProductAttribute": "商品属性",
"ProductAttributeNames": "商品属性",

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

@ -6,7 +6,8 @@
"ManageYourProfile": "管理個人資料",
"Menu:Product": "商品",
"Product": "商品",
"ProductStore": "店鋪商品",
"ProductStoreId": "店鋪 ID",
"ProductCategoryId": "類目 ID",
"ProductProductGroupName": "商品組",
"ProductProductGroupDisplayName": "商品組名稱",
"ProductDetailId": "商品詳情 ID",
@ -14,10 +15,8 @@
"ProductDisplayName": "商品名稱",
"ProductDisplayOrder": "展示順序",
"ProductSold": "已售",
"ProductDetailProductId": "商品 ID",
"ProductDetailProductSkuId": "商品 SKU ID",
"ProductDetailStoreId": "店铺 ID",
"ProductDetailDescription": "內容",
"ProductDetailDisplayOrder": "展示順序",
"ProductCategory": "所屬類目",
"ProductAttribute": "商品屬性",
"ProductAttributeNames": "商品屬性",

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

@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using EasyAbp.EShop.Stores.Stores;
using Volo.Abp.Data;
namespace EasyAbp.EShop.Products.Products
{
public interface IProduct : IHasExtraProperties
public interface IProduct : IHasExtraProperties, IMultiStore
{
string ProductGroupName { get; }

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

@ -9,6 +9,8 @@ namespace EasyAbp.EShop.Products.Products
{
public Guid Id { get; set; }
public Guid StoreId { get; set; }
public string ProductGroupName { get; set; }
public Guid ProductDetailId { get; set; }

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp.EShop.Products.Domain.csproj

@ -12,7 +12,6 @@
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(AbpVersion)" />
<ProjectReference Include="..\..\..\EasyAbp.EShop.Orders\src\EasyAbp.EShop.Orders.Domain.Shared\EasyAbp.EShop.Orders.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\EasyAbp.EShop.Stores\src\EasyAbp.EShop.Stores.Domain.Shared\EasyAbp.EShop.Stores.Domain.Shared.csproj" />
<ProjectReference Include="..\EasyAbp.EShop.Products.Domain.Shared\EasyAbp.EShop.Products.Domain.Shared.csproj" />
</ItemGroup>

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/EShopProductsDomainModule.cs

@ -12,7 +12,6 @@ namespace EasyAbp.EShop.Products
{
[DependsOn(
typeof(EShopProductsDomainSharedModule),
typeof(EShopStoresDomainSharedModule),
typeof(AbpTreesDomainModule)
)]
public class EShopProductsDomainModule : AbpModule

4
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductDetails/ProductDetail.cs

@ -6,6 +6,8 @@ namespace EasyAbp.EShop.Products.ProductDetails
{
public class ProductDetail : FullAuditedAggregateRoot<Guid>
{
public virtual Guid? StoreId { get; protected set; }
[CanBeNull]
public virtual string Description { get; protected set; }
@ -13,8 +15,10 @@ namespace EasyAbp.EShop.Products.ProductDetails
public ProductDetail(
Guid id,
Guid? storeId,
[CanBeNull] string description) : base(id)
{
StoreId = storeId;
Description = description;
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductHistories/IProductHistoryRecorder.cs

@ -4,7 +4,7 @@ using Volo.Abp.EventBus;
namespace EasyAbp.EShop.Products.ProductHistories
{
public interface IProductHistoryRecorder : ILocalEventHandler<EntityChangedEventData<Product>>
public interface IProductHistoryRecorder
{
}

6
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductHistories/ProductHistoryRecorder.cs

@ -2,13 +2,17 @@
using EasyAbp.EShop.Products.Products;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
using Volo.Abp.Guids;
using Volo.Abp.Json;
using Volo.Abp.Uow;
namespace EasyAbp.EShop.Products.ProductHistories
{
public class ProductHistoryRecorder : IProductHistoryRecorder, ITransientDependency
public class ProductHistoryRecorder :
ILocalEventHandler<EntityChangedEventData<Product>>,
IProductHistoryRecorder,
ITransientDependency
{
private readonly IGuidGenerator _guidGenerator;
private readonly IJsonSerializer _jsonSerializer;

12
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductStores/IProductStoreRepository.cs

@ -1,12 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace EasyAbp.EShop.Products.ProductStores
{
public interface IProductStoreRepository : IRepository<ProductStore, Guid>
{
Task<ProductStore> GetAsync(Guid productId, Guid storeId, bool includeDetails = true, CancellationToken cancellationToken = default);
}
}

33
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductStores/ProductStore.cs

@ -1,33 +0,0 @@
using System;
using EasyAbp.EShop.Stores.Stores;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace EasyAbp.EShop.Products.ProductStores
{
public class ProductStore : FullAuditedAggregateRoot<Guid>, IMultiTenant, IMultiStore
{
public virtual Guid? TenantId { get; protected set; }
public virtual Guid StoreId { get; protected set; }
public virtual Guid ProductId { get; protected set; }
public virtual bool IsOwner { get; protected set; }
protected ProductStore() {}
public ProductStore(
Guid id,
Guid? tenantId,
Guid storeId,
Guid productId,
bool isOwner) : base(id)
{
TenantId = tenantId;
StoreId = storeId;
ProductId = productId;
IsOwner = isOwner;
}
}
}

8
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductInventoryProvider.cs

@ -26,12 +26,12 @@ namespace EasyAbp.EShop.Products.Products
_productInventoryRepository = productInventoryRepository;
}
public virtual async Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId)
public virtual async Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku)
{
return await _productInventoryRepository.GetInventoryDataAsync(productSku.Id);
}
public virtual async Task<Dictionary<Guid, InventoryDataModel>> GetInventoryDataDictionaryAsync(Product product, Guid storeId)
public virtual async Task<Dictionary<Guid, InventoryDataModel>> GetInventoryDataDictionaryAsync(Product product)
{
var dict = await _productInventoryRepository.GetInventoryDataDictionaryAsync(product.ProductSkus
.Select(sku => sku.Id).ToList());
@ -44,14 +44,14 @@ namespace EasyAbp.EShop.Products.Products
return dict;
}
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool decreaseSold)
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, int quantity, bool decreaseSold)
{
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);
return await TryIncreaseInventoryAsync(productInventory, quantity, decreaseSold);
}
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool increaseSold)
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, int quantity, bool increaseSold)
{
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductPriceProvider.cs

@ -6,7 +6,7 @@ namespace EasyAbp.EShop.Products.Products
{
public class DefaultProductPriceProvider : IProductPriceProvider, ITransientDependency
{
public virtual Task<decimal> GetPriceAsync(Product product, ProductSku productSku, Guid storeId)
public virtual Task<decimal> GetPriceAsync(Product product, ProductSku productSku)
{
return Task.FromResult(productSku.Price);
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountProvider.cs

@ -5,6 +5,6 @@ namespace EasyAbp.EShop.Products.Products
{
public interface IProductDiscountProvider
{
Task<decimal> GetDiscountedPriceAsync(Product product, ProductSku productSku, Guid storeId, decimal currentPrice);
Task<decimal> GetDiscountedPriceAsync(Product product, ProductSku productSku, decimal currentPrice);
}
}

8
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductInventoryProvider.cs

@ -6,12 +6,12 @@ namespace EasyAbp.EShop.Products.Products
{
public interface IProductInventoryProvider
{
Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId);
Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku);
Task<Dictionary<Guid, InventoryDataModel>> GetInventoryDataDictionaryAsync(Product product, Guid storeId);
Task<Dictionary<Guid, InventoryDataModel>> GetInventoryDataDictionaryAsync(Product product);
Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool decreaseSold);
Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, int quantity, bool decreaseSold);
Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool increaseSold);
Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, int quantity, bool increaseSold);
}
}

12
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductManager.cs

@ -7,7 +7,7 @@ namespace EasyAbp.EShop.Products.Products
{
public interface IProductManager : IDomainService
{
Task<Product> CreateAsync(Product product, Guid? storeId = null, IEnumerable<Guid> categoryIds = null);
Task<Product> CreateAsync(Product product, IEnumerable<Guid> categoryIds = null);
Task<Product> UpdateAsync(Product product, IEnumerable<Guid> categoryIds = null);
@ -21,14 +21,14 @@ namespace EasyAbp.EShop.Products.Products
Task<Product> DeleteSkuAsync(Product product, ProductSku productSku);
Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, int quantity);
Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, int quantity);
Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId);
Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku);
Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool reduceSold);
Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, int quantity, bool reduceSold);
Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool increaseSold);
Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, int quantity, bool increaseSold);
Task<PriceDataModel> GetProductPriceAsync(Product product, ProductSku productSku, Guid storeId);
Task<PriceDataModel> GetProductPriceAsync(Product product, ProductSku productSku);
}
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductPriceProvider.cs

@ -5,6 +5,6 @@ namespace EasyAbp.EShop.Products.Products
{
public interface IProductPriceProvider
{
Task<decimal> GetPriceAsync(Product product, ProductSku productSku, Guid storeId);
Task<decimal> GetPriceAsync(Product product, ProductSku productSku);
}
}

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

@ -6,8 +6,8 @@ namespace EasyAbp.EShop.Products.Products
{
public interface IProductRepository : IRepository<Product, Guid>
{
IQueryable<Product> GetQueryable(Guid storeId, Guid? categoryId = null);
IQueryable<Product> GetQueryable(Guid categoryId);
IQueryable<Product> WithDetails(Guid storeId, Guid? categoryId = null);
IQueryable<Product> WithDetails(Guid categoryId);
}
}

6
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderCreatedEventHandler.cs

@ -59,8 +59,7 @@ namespace EasyAbp.EShop.Products.Products
continue;
}
if (!await _productManager.IsInventorySufficientAsync(product, productSku, eventData.Entity.StoreId,
orderLine.Quantity))
if (!await _productManager.IsInventorySufficientAsync(product, productSku, orderLine.Quantity))
{
await PublishResultEventAsync(eventData, false);
@ -78,8 +77,7 @@ namespace EasyAbp.EShop.Products.Products
foreach (var model in models)
{
if (await _productManager.TryReduceInventoryAsync(model.Product, model.ProductSku, model.StoreId,
model.Quantity, true))
if (await _productManager.TryReduceInventoryAsync(model.Product, model.ProductSku, model.Quantity, true))
{
continue;
}

6
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderPaidEventHandler.cs

@ -58,8 +58,7 @@ namespace EasyAbp.EShop.Products.Products
continue;
}
if (!await _productManager.IsInventorySufficientAsync(product, productSku, eventData.Order.StoreId,
orderLine.Quantity))
if (!await _productManager.IsInventorySufficientAsync(product, productSku, orderLine.Quantity))
{
await PublishResultEventAsync(eventData, false);
@ -77,8 +76,7 @@ namespace EasyAbp.EShop.Products.Products
foreach (var model in models)
{
if (await _productManager.TryReduceInventoryAsync(model.Product, model.ProductSku, model.StoreId,
model.Quantity, true))
if (await _productManager.TryReduceInventoryAsync(model.Product, model.ProductSku, model.Quantity, true))
{
continue;
}

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

@ -1,12 +1,15 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Domain.Entities.Auditing;
namespace EasyAbp.EShop.Products.Products
{
public class Product : FullAuditedAggregateRoot<Guid>, IProduct
{
public virtual Guid StoreId { get; protected set; }
[NotNull]
public virtual string ProductGroupName { get; protected set; }
@ -41,6 +44,7 @@ namespace EasyAbp.EShop.Products.Products
public Product(
Guid id,
Guid storeId,
[NotNull] string productGroupName,
Guid productDetailId,
[CanBeNull] string code,
@ -53,6 +57,7 @@ namespace EasyAbp.EShop.Products.Products
int displayOrder
) : base(id)
{
StoreId = storeId;
ProductGroupName = productGroupName;
ProductDetailId = productDetailId;
UniqueName = code?.Trim();
@ -74,7 +79,7 @@ namespace EasyAbp.EShop.Products.Products
ProductSkus ??= new List<ProductSku>();
}
public void TrimCode()
public void TrimUniqueName()
{
UniqueName = UniqueName?.Trim();
}

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

@ -4,7 +4,6 @@ using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Options.ProductGroups;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.ProductStores;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Domain.Services;
@ -13,7 +12,6 @@ namespace EasyAbp.EShop.Products.Products
public class ProductManager : DomainService, IProductManager
{
private readonly IProductRepository _productRepository;
private readonly IProductStoreRepository _productStoreRepository;
private readonly IProductPriceProvider _productPriceProvider;
private readonly IProductCategoryRepository _productCategoryRepository;
private readonly IProductInventoryProvider _productInventoryProvider;
@ -21,24 +19,21 @@ namespace EasyAbp.EShop.Products.Products
public ProductManager(
IProductRepository productRepository,
IProductStoreRepository productStoreRepository,
IProductPriceProvider productPriceProvider,
IProductCategoryRepository productCategoryRepository,
IProductInventoryProvider productInventoryProvider,
IProductGroupConfigurationProvider productGroupConfigurationProvider)
{
_productRepository = productRepository;
_productStoreRepository = productStoreRepository;
_productPriceProvider = productPriceProvider;
_productCategoryRepository = productCategoryRepository;
_productInventoryProvider = productInventoryProvider;
_productGroupConfigurationProvider = productGroupConfigurationProvider;
}
public virtual async Task<Product> CreateAsync(Product product, Guid? storeId = null,
IEnumerable<Guid> categoryIds = null)
public virtual async Task<Product> CreateAsync(Product product, IEnumerable<Guid> categoryIds = null)
{
product.TrimCode();
product.TrimUniqueName();
await CheckProductGroupNameAsync(product);
@ -50,11 +45,6 @@ namespace EasyAbp.EShop.Products.Products
await UpdateProductCategoriesAsync(product.Id, categoryIds);
if (storeId.HasValue)
{
await AddProductToStoreAsync(product.Id, storeId.Value);
}
return product;
}
@ -153,12 +143,6 @@ namespace EasyAbp.EShop.Products.Products
return await _productRepository.UpdateAsync(product, true);
}
protected virtual async Task AddProductToStoreAsync(Guid productId, Guid storeId)
{
await _productStoreRepository.InsertAsync(new ProductStore(GuidGenerator.Create(), CurrentTenant.Id,
storeId, productId, true), true);
}
protected virtual async Task CheckProductUniqueNameAsync(Product product)
{
if (product.UniqueName.IsNullOrEmpty())
@ -201,38 +185,37 @@ namespace EasyAbp.EShop.Products.Products
}
}
public virtual async Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
public virtual async Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, int quantity)
{
var inventoryData = await _productInventoryProvider.GetInventoryDataAsync(product, productSku, storeId);
var inventoryData = await _productInventoryProvider.GetInventoryDataAsync(product, productSku);
return product.InventoryStrategy == InventoryStrategy.NoNeed || inventoryData.Inventory - quantity >= 0;
}
public virtual async Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId)
public virtual async Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku)
{
return await _productInventoryProvider.GetInventoryDataAsync(product, productSku, storeId);
return await _productInventoryProvider.GetInventoryDataAsync(product, productSku);
}
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool reduceSold)
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, int quantity, bool reduceSold)
{
return await _productInventoryProvider.TryIncreaseInventoryAsync(product, productSku, storeId, quantity, reduceSold);
return await _productInventoryProvider.TryIncreaseInventoryAsync(product, productSku, quantity, reduceSold);
}
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool increaseSold)
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, int quantity, bool increaseSold)
{
return await _productInventoryProvider.TryReduceInventoryAsync(product, productSku, storeId, quantity,
increaseSold);
return await _productInventoryProvider.TryReduceInventoryAsync(product, productSku, quantity, increaseSold);
}
public virtual async Task<PriceDataModel> GetProductPriceAsync(Product product, ProductSku productSku, Guid storeId)
public virtual async Task<PriceDataModel> GetProductPriceAsync(Product product, ProductSku productSku)
{
var price = await _productPriceProvider.GetPriceAsync(product, productSku, storeId);
var price = await _productPriceProvider.GetPriceAsync(product, productSku);
var discountedPrice = price;
foreach (var provider in ServiceProvider.GetServices<IProductDiscountProvider>())
{
discountedPrice = await provider.GetDiscountedPriceAsync(product, productSku, storeId, discountedPrice);
discountedPrice = await provider.GetDiscountedPriceAsync(product, productSku, discountedPrice);
}
return new PriceDataModel

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductSku.cs

@ -64,7 +64,7 @@ namespace EasyAbp.EShop.Products.Products
this.SetDefaultsForExtraProperties();
}
public void TrimCode()
internal void TrimCode()
{
Name = Name?.Trim();
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/EShopProductsEntityFrameworkCoreModule.cs

@ -2,7 +2,6 @@ using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.Abp.Trees.EntityFrameworkCore;
using EasyAbp.EShop.Products.ProductDetailHistories;
using EasyAbp.EShop.Products.ProductHistories;
using EasyAbp.EShop.Products.ProductStores;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.Categories;
using EasyAbp.EShop.Products.ProductDetails;
@ -31,7 +30,6 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
options.AddRepository<Product, ProductRepository>();
options.AddRepository<ProductDetail, ProductDetailRepository>();
options.AddRepository<ProductCategory, ProductCategoryRepository>();
options.AddRepository<ProductStore, ProductStoreRepository>();
options.AddRepository<ProductHistory, ProductHistoryRepository>();
options.AddRepository<ProductDetailHistory, ProductDetailHistoryRepository>();
options.AddRepository<ProductInventory, ProductInventoryRepository>();

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/IProductsDbContext.cs

@ -5,7 +5,6 @@ using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Categories;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.ProductDetails;
using EasyAbp.EShop.Products.ProductStores;
using EasyAbp.EShop.Products.ProductHistories;
using EasyAbp.EShop.Products.ProductDetailHistories;
using EasyAbp.EShop.Products.ProductInventories;
@ -25,7 +24,6 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
DbSet<ProductSku> ProductSkus { get; set; }
DbSet<Category> Categories { get; set; }
DbSet<ProductCategory> ProductCategories { get; set; }
DbSet<ProductStore> ProductStores { get; set; }
DbSet<ProductHistory> ProductHistories { get; set; }
DbSet<ProductDetailHistory> ProductDetailHistories { get; set; }
DbSet<ProductInventory> ProductInventories { get; set; }

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs

@ -5,7 +5,6 @@ using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Categories;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.ProductDetails;
using EasyAbp.EShop.Products.ProductStores;
using EasyAbp.EShop.Products.ProductHistories;
using EasyAbp.EShop.Products.ProductDetailHistories;
using EasyAbp.EShop.Products.ProductInventories;
@ -25,7 +24,6 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
public DbSet<ProductSku> ProductSkus { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<ProductCategory> ProductCategories { get; set; }
public DbSet<ProductStore> ProductStores { get; set; }
public DbSet<ProductHistory> ProductHistories { get; set; }
public DbSet<ProductDetailHistory> ProductDetailHistories { get; set; }
public DbSet<ProductInventory> ProductInventories { get; set; }

8
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs

@ -1,7 +1,6 @@
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.ProductDetailHistories;
using EasyAbp.EShop.Products.ProductHistories;
using EasyAbp.EShop.Products.ProductStores;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.Categories;
using EasyAbp.EShop.Products.Products;
@ -103,13 +102,6 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
/* Configure more properties here */
});
builder.Entity<ProductStore>(b =>
{
b.ToTable(options.TablePrefix + "ProductStores", options.Schema);
b.ConfigureByConvention();
/* Configure more properties here */
});
builder.Entity<ProductHistory>(b =>
{
b.ToTable(options.TablePrefix + "ProductHistories", options.Schema);

29
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/ProductStores/ProductStoreRepository.cs

@ -1,29 +0,0 @@
using EasyAbp.EShop.Products.EntityFrameworkCore;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace EasyAbp.EShop.Products.ProductStores
{
public class ProductStoreRepository : EfCoreRepository<IProductsDbContext, ProductStore, Guid>, IProductStoreRepository
{
public ProductStoreRepository(IDbContextProvider<IProductsDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<ProductStore> GetAsync(Guid productId, Guid storeId, bool includeDetails = true, CancellationToken cancellationToken = default)
{
var entity = await FindAsync(x => x.ProductId == productId && x.StoreId == storeId, includeDetails, cancellationToken);
if (entity == null)
{
throw new EntityNotFoundException(typeof(ProductStore), new { ProductId = productId, StoreId = storeId });
}
return entity;
}
}
}

13
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/DuplicatedProductUniqueNameException.cs

@ -0,0 +1,13 @@
using Volo.Abp;
namespace EasyAbp.EShop.Products.Products
{
public class DuplicatedProductUniqueNameException : BusinessException
{
public DuplicatedProductUniqueNameException(string uniqueName) : base("DuplicatedProductUniqueName",
$"The product unique name \"{uniqueName}\" is duplicated.")
{
}
}
}

52
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/ProductRepository.cs

@ -1,5 +1,7 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -13,55 +15,45 @@ namespace EasyAbp.EShop.Products.Products
{
}
public override IQueryable<Product> WithDetails()
public override async Task<Product> UpdateAsync(Product entity, bool autoSave = false, CancellationToken cancellationToken = new CancellationToken())
{
return base.WithDetails()
.Include(x => x.ProductAttributes).ThenInclude(x => x.ProductAttributeOptions)
.Include(x => x.ProductSkus);
await CheckUniqueNameAsync(entity, cancellationToken);
return await base.UpdateAsync(entity, autoSave, cancellationToken);
}
public IQueryable<Product> GetQueryable(Guid storeId, Guid? categoryId = null)
public override async Task<Product> InsertAsync(Product entity, bool autoSave = false, CancellationToken cancellationToken = new CancellationToken())
{
var queryable = GetStoreQueryable(storeId);
await CheckUniqueNameAsync(entity, cancellationToken);
if (categoryId.HasValue)
{
queryable = JoinProductCategories(queryable, categoryId.Value);
}
return queryable;
return await base.InsertAsync(entity, autoSave, cancellationToken);
}
public IQueryable<Product> WithDetails(Guid storeId, Guid? categoryId = null)
protected virtual async Task CheckUniqueNameAsync(Product entity, CancellationToken cancellationToken = new CancellationToken())
{
var queryable = WithStoreDetails(storeId);
if (categoryId.HasValue)
if (await DbSet.AnyAsync(
x => x.StoreId == entity.StoreId && x.UniqueName == entity.UniqueName && x.Id != entity.Id,
cancellationToken))
{
queryable = JoinProductCategories(queryable, categoryId.Value);
throw new DuplicatedProductUniqueNameException(entity.UniqueName);
}
return queryable;
}
protected virtual IQueryable<Product> GetStoreQueryable(Guid storeId)
public override IQueryable<Product> WithDetails()
{
return JoinProductStores(GetQueryable(), storeId);
return base.WithDetails()
.Include(x => x.ProductAttributes).ThenInclude(x => x.ProductAttributeOptions)
.Include(x => x.ProductSkus);
}
protected virtual IQueryable<Product> WithStoreDetails(Guid storeId)
public IQueryable<Product> GetQueryable(Guid categoryId)
{
return JoinProductStores(WithDetails(), storeId);
return JoinProductCategories(DbSet, categoryId);
}
protected virtual IQueryable<Product> JoinProductStores(IQueryable<Product> queryable, Guid storeId)
public IQueryable<Product> WithDetails(Guid categoryId)
{
return queryable.Join(
DbContext.ProductStores.Where(productStore => productStore.StoreId == storeId),
product => product.Id,
productStore => productStore.ProductId,
(product, productStore) => product
);
return JoinProductCategories(WithDetails(), categoryId);
}
protected virtual IQueryable<Product> JoinProductCategories(IQueryable<Product> queryable, Guid categoryId)

10
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/ProductDetails/ProductDetailController.cs

@ -26,7 +26,7 @@ namespace EasyAbp.EShop.Products.ProductDetails
}
[HttpGet]
public Task<PagedResultDto<ProductDetailDto>> GetListAsync(PagedAndSortedResultRequestDto input)
public Task<PagedResultDto<ProductDetailDto>> GetListAsync(GetProductDetailListInput input)
{
return _service.GetListAsync(input);
}
@ -50,13 +50,5 @@ namespace EasyAbp.EShop.Products.ProductDetails
{
return _service.DeleteAsync(id);
}
[HttpDelete]
[Route("{id}/abandoned")]
[RemoteService(false)]
public Task DeleteAsync(Guid id, Guid storeId)
{
return _service.DeleteAsync(id, storeId);
}
}
}

40
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/Products/ProductController.cs

@ -18,14 +18,6 @@ namespace EasyAbp.EShop.Products.Products
_service = service;
}
[HttpGet]
[Route("{id}/abandoned")]
[RemoteService(false)]
public Task<ProductDto> GetAsync(Guid id)
{
return _service.GetAsync(id);
}
[HttpGet]
public Task<PagedResultDto<ProductDto>> GetListAsync(GetProductListDto input)
{
@ -46,53 +38,45 @@ namespace EasyAbp.EShop.Products.Products
}
[HttpDelete]
[Route("{id}/abandoned")]
[RemoteService(false)]
[Route("{id}")]
public Task DeleteAsync(Guid id)
{
return _service.DeleteAsync(id);
}
[HttpDelete]
[Route("{id}")]
public Task DeleteAsync(Guid id, Guid storeId)
{
return _service.DeleteAsync(id, storeId);
}
[HttpPost]
[Route("{id}/sku")]
public Task<ProductDto> CreateSkuAsync(Guid id, Guid storeId, CreateProductSkuDto input)
public Task<ProductDto> CreateSkuAsync(Guid id, CreateProductSkuDto input)
{
return _service.CreateSkuAsync(id, storeId, input);
return _service.CreateSkuAsync(id, input);
}
[HttpPut]
[Route("{id}/sku/{productSkuId}")]
public Task<ProductDto> UpdateSkuAsync(Guid id, Guid productSkuId, Guid storeId, UpdateProductSkuDto input)
public Task<ProductDto> UpdateSkuAsync(Guid id, Guid productSkuId, UpdateProductSkuDto input)
{
return _service.UpdateSkuAsync(id, productSkuId, storeId, input);
return _service.UpdateSkuAsync(id, productSkuId, input);
}
[HttpGet]
[Route("{id}")]
public Task<ProductDto> GetAsync(Guid id, Guid storeId)
public Task<ProductDto> GetAsync(Guid id)
{
return _service.GetAsync(id, storeId);
return _service.GetAsync(id);
}
[HttpGet]
[Route("by-code/{storeId}")]
public Task<ProductDto> GetByCodeAsync(string code, Guid storeId)
[Route("by-code/{code}")]
public Task<ProductDto> GetByCodeAsync(Guid storeId, string code)
{
return _service.GetByCodeAsync(code, storeId);
return _service.GetByCodeAsync(storeId, code);
}
[HttpDelete]
[Route("{id}/sku/{productSkuId}")]
public Task<ProductDto> DeleteSkuAsync(Guid id, Guid productSkuId, Guid storeId)
public Task<ProductDto> DeleteSkuAsync(Guid id, Guid productSkuId)
{
return _service.DeleteSkuAsync(id, productSkuId, storeId);
return _service.DeleteSkuAsync(id, productSkuId);
}
[HttpGet]

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/EasyAbp.EShop.Products.Web.csproj

@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared" Version="$(AbpVersion)" />
<PackageReference Include="EasyAbp.Abp.TagHelperPlus" Version="0.3.3" />
<PackageReference Include="EasyAbp.Abp.TagHelperPlus" Version="0.6.0" />
</ItemGroup>
<ItemGroup>

4
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Menus/ProductsMenuContributor.cs

@ -24,14 +24,14 @@ namespace EasyAbp.EShop.Products.Web.Menus
var productManagementMenuItem = new ApplicationMenuItem(ProductsMenus.Prefix, l["Menu:ProductManagement"]);
if (await context.IsGrantedAsync(ProductsPermissions.Categories.Default))
if (await context.IsGrantedAsync(ProductsPermissions.Categories.Manage))
{
productManagementMenuItem.AddItem(
new ApplicationMenuItem(ProductsMenus.Category, l["Menu:Category"], "/EShop/Products/Categories/Category")
);
}
if (await context.IsGrantedAsync(ProductsPermissions.Products.Default))
if (await context.IsGrantedAsync(ProductsPermissions.Products.Manage))
{
productManagementMenuItem.AddItem(
new ApplicationMenuItem(ProductsMenus.Product, l["Menu:Product"], "/EShop/Products/Products/Product")

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

@ -17,11 +17,8 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
{
public class CreateModalModel : ProductsPageModel
{
[BindProperty(SupportsGet = true)]
public Guid StoreId { get; set; }
[BindProperty]
public CreateEditProductViewModel Product { get; set; }
public CreateProductViewModel Product { get; set; }
public ICollection<SelectListItem> ProductGroups { get; set; }
@ -41,7 +38,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
_service = service;
}
public virtual async Task OnGetAsync(Guid? categoryId)
public virtual async Task OnGetAsync(Guid storeId, Guid? categoryId)
{
ProductGroups =
(await _service.GetProductGroupListAsync()).Items
@ -52,12 +49,12 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
{ MaxResultCount = LimitedResultRequestDto.MaxMaxResultCount }))?.Items
.Select(dto => new SelectListItem(dto.DisplayName, dto.Id.ToString())).ToList();
Product = new CreateEditProductViewModel
Product = new CreateProductViewModel
{
StoreId = StoreId,
ProductDetail = new CreateEditProductDetailViewModel
StoreId = storeId,
ProductDetail = new CreateProductDetailViewModel
{
StoreId = StoreId
StoreId = storeId
}
};
@ -71,9 +68,9 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
{
var detail = await _productDetailAppService.CreateAsync(
ObjectMapper
.Map<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>(Product.ProductDetail));
.Map<CreateProductDetailViewModel, CreateUpdateProductDetailDto>(Product.ProductDetail));
var createDto = ObjectMapper.Map<CreateEditProductViewModel, CreateUpdateProductDto>(Product);
var createDto = ObjectMapper.Map<CreateProductViewModel, CreateUpdateProductDto>(Product);
createDto.ProductDetailId = detail.Id;

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

@ -24,7 +24,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
public Guid Id { get; set; }
[BindProperty]
public CreateEditProductViewModel Product { get; set; }
public EditProductViewModel Product { get; set; }
public ICollection<SelectListItem> ProductGroups { get; set; }
@ -47,7 +47,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
_service = service;
}
public virtual async Task OnGetAsync(Guid storeId)
public virtual async Task OnGetAsync()
{
ProductGroups =
(await _service.GetProductGroupListAsync()).Items
@ -58,11 +58,11 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
{MaxResultCount = LimitedResultRequestDto.MaxMaxResultCount}))?.Items
.Select(dto => new SelectListItem(dto.DisplayName, dto.Id.ToString())).ToList();
var productDto = await _service.GetAsync(Id, storeId);
var productDto = await _service.GetAsync(Id);
var detailDto = await _productDetailAppService.GetAsync(productDto.ProductDetailId);
Product = ObjectMapper.Map<ProductDto, CreateEditProductViewModel>(productDto);
Product = ObjectMapper.Map<ProductDto, EditProductViewModel>(productDto);
Product.CategoryIds = (await _productCategoryAppService.GetListAsync(new GetProductCategoryListDto
{
@ -70,26 +70,23 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
MaxResultCount = LimitedResultRequestDto.MaxMaxResultCount
})).Items.Select(x => x.CategoryId).ToList();
Product.ProductDetail = new CreateEditProductDetailViewModel
Product.ProductDetail = new EditProductDetailViewModel
{
StoreId = storeId,
Description = detailDto.Description
};
Product.StoreId = storeId;
}
public virtual async Task<IActionResult> OnPostAsync()
{
var product = await _service.GetAsync(Id, Product.StoreId);
var product = await _service.GetAsync(Id);
var detail = await _productDetailAppService.GetAsync(product.ProductDetailId);
await _productDetailAppService.UpdateAsync(detail.Id,
ObjectMapper
.Map<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>(Product.ProductDetail));
.Map<EditProductDetailViewModel, CreateUpdateProductDetailDto>(Product.ProductDetail));
var updateProductDto = ObjectMapper.Map<CreateEditProductViewModel, CreateUpdateProductDto>(Product);
var updateProductDto = ObjectMapper.Map<EditProductViewModel, CreateUpdateProductDto>(Product);
updateProductDto.ProductDetailId = detail.Id;

87
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml

@ -22,37 +22,60 @@
<abp-style src="/Pages/EShop/Products/Products/Product/index.css"/>
}
<script>
let storeId = '@Model.StoreId';
let categoryId = '@Model.CategoryId';
let storeId = '@Model.Filter.StoreId';
let categoryId = '@Model.Filter.CategoryId';
</script>
<abp-card>
<abp-card-header>
<abp-row>
<abp-column size-md="_6">
<abp-card-title>@L["Product"] - @Model.StoreName</abp-card-title>
</abp-column>
<abp-column size-md="_6" class="text-right">
<abp-button id="NewProductButton"
text="@L["CreateProduct"].Value"
icon="plus"
button-type="Primary" />
</abp-column>
</abp-row>
</abp-card-header>
<abp-card-body>
<abp-table striped-rows="true" id="ProductTable" class="nowrap">
<thead>
<tr>
<th>@L["Actions"]</th>
<th>@L["ProductProductGroupDisplayName"]</th>
<th>@L["ProductUniqueName"]</th>
<th>@L["ProductDisplayName"]</th>
<th>@L["ProductInventoryStrategy"]</th>
<th>@L["ProductSold"]</th>
<th>@L["ProductIsPublished"]</th>
</tr>
</thead>
</abp-table>
</abp-card-body>
</abp-card>
@if (Model.Filter.StoreId == null)
{
<abp-dynamic-form abp-model="Filter" data-ajaxForm="true" asp-page="Index">
<abp-card>
<abp-card-header>
<abp-row>
<abp-column size-md="_6">
<abp-card-title>@L["Product"]</abp-card-title>
</abp-column>
</abp-row>
</abp-card-header>
<abp-card-body>
<abp-form-content></abp-form-content>
</abp-card-body>
<abp-modal-footer>
<abp-button id="enter-button" button-type="Primary" text="Enter"/>
</abp-modal-footer>
</abp-card>
</abp-dynamic-form>
}
else
{
<abp-card>
<abp-card-header>
<abp-row>
<abp-column size-md="_6">
<abp-card-title>@L["Product"] - @Model.StoreName</abp-card-title>
</abp-column>
<abp-column size-md="_6" class="text-right">
<abp-button id="NewProductButton"
text="@L["CreateProduct"].Value"
icon="plus"
button-type="Primary" />
</abp-column>
</abp-row>
</abp-card-header>
<abp-card-body>
<abp-table striped-rows="true" id="ProductTable" class="nowrap">
<thead>
<tr>
<th>@L["Actions"]</th>
<th>@L["ProductProductGroupDisplayName"]</th>
<th>@L["ProductUniqueName"]</th>
<th>@L["ProductDisplayName"]</th>
<th>@L["ProductInventoryStrategy"]</th>
<th>@L["ProductSold"]</th>
<th>@L["ProductIsPublished"]</th>
</tr>
</thead>
</abp-table>
</abp-card-body>
</abp-card>
}

28
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml.cs

@ -1,10 +1,11 @@
using System;
using EasyAbp.EShop.Stores.StoreOwners;
using EasyAbp.EShop.Stores.StoreOwners.Dtos;
using EasyAbp.EShop.Stores.Stores;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewModels;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
{
@ -14,13 +15,10 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
private readonly IStoreOwnerAppService _storeOwnerAppService;
[BindProperty(SupportsGet = true)]
public Guid? StoreId { get; set; }
[BindProperty(SupportsGet = true)]
public Guid? CategoryId { get; set; }
public ProductListFilterViewModel Filter { get; set; }
public string StoreName { get; set; }
public IndexModel(IStoreAppService storeAppService,
IStoreOwnerAppService storeOwnerAppService)
{
@ -30,24 +28,10 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product
public virtual async Task OnGetAsync()
{
//TODO: Need to handle: when StoreId is empty, and current user owns multiple store
if (!StoreId.HasValue && CurrentUser.Id.HasValue)
if (Filter.StoreId.HasValue)
{
var storeOwners = await _storeOwnerAppService.GetListAsync(new GetStoreOwnerListDto
{
OwnerUserId = CurrentUser.Id.Value,
});
StoreId = storeOwners.Items.FirstOrDefault()?.StoreId;
StoreName = (await _storeAppService.GetAsync(Filter.StoreId.Value)).Name;
}
if (!StoreId.HasValue)
{
var defaultStore = await _storeAppService.GetDefaultAsync();
StoreId = defaultStore.Id;
}
StoreName = (await _storeAppService.GetAsync(StoreId.Value)).Name;
}
}
}

10
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateEditProductDetailViewModel.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateProductDetailViewModel.cs

@ -9,14 +9,10 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewModels
{
public class CreateEditProductDetailViewModel
public class CreateProductDetailViewModel : EditProductDetailViewModel
{
[HiddenInput]
[Display(Name = "ProductStore")]
public Guid StoreId { get; set; }
[TextArea(Rows = 4)]
[Display(Name = "ProductDetailDescription")]
public string Description { get; set; }
[Display(Name = "ProductDetailStoreId")]
public Guid? StoreId { get; set; }
}
}

74
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateProductViewModel.cs

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using EasyAbp.Abp.TagHelperPlus.EasySelector;
using EasyAbp.EShop.Products.Products;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewModels
{
public class CreateProductViewModel : IValidatableObject
{
[HiddenInput]
[Display(Name = "ProductStoreId")]
public Guid StoreId { get; set; }
[Required]
[SelectItems("ProductGroups")]
[Display(Name = "ProductProductGroupName")]
public string ProductGroupName { get; set; }
// [SelectItems("Categories")]
[EasySelector(
getListedDataSourceUrl: ProductsConsts.GetCategorySummaryListedDataSourceUrl,
getSingleDataSourceUrl: ProductsConsts.GetCategorySummarySingleDataSourceUrl,
keyPropertyName: "id",
textPropertyName: "displayName")]
[Display(Name = "ProductCategory")]
public List<Guid> CategoryIds { get; set; }
[Display(Name = "ProductUniqueName")]
public string UniqueName { get; set; }
[Required]
[Display(Name = "ProductDisplayName")]
public string DisplayName { get; set; }
public CreateProductDetailViewModel ProductDetail { get; set; }
[Required]
[Placeholder("ProductAttributeNamesPlaceholder")]
[Display(Name = "ProductAttributeNames")]
public string ProductAttributeNames { get; set; }
[Required]
[TextArea(Rows = 4)]
[Placeholder("ProductAttributeOptionNamesPlaceholder")]
[Display(Name = "ProductAttributeOptionNames")]
public string ProductAttributeOptionNames { get; set; }
[Display(Name = "ProductInventoryStrategy")]
public InventoryStrategy InventoryStrategy { get; set; }
[Display(Name = "ProductDisplayOrder")]
public int DisplayOrder { get; set; }
[Display(Name = "ProductMediaResources")]
public string MediaResources { get; set; }
[Display(Name = "ProductIsPublished")]
public bool IsPublished { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (StoreId != ProductDetail.StoreId)
{
yield return new ValidationResult(
"The StoreId should be same as the ProductDetail.StoreId.",
new[] {"StoreId"}
);
}
}
}
}

12
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/EditProductDetailViewModel.cs

@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewModels
{
public class EditProductDetailViewModel
{
[TextArea(Rows = 4)]
[Display(Name = "ProductDetailDescription")]
public string Description { get; set; }
}
}

11
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateEditProductViewModel.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/EditProductViewModel.cs

@ -1,21 +1,14 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using EasyAbp.Abp.TagHelperPlus.EasySelector;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewModels
{
public class CreateEditProductViewModel
public class EditProductViewModel
{
[HiddenInput]
[Display(Name = "ProductStore")]
public Guid StoreId { get; set; }
[Required]
[SelectItems("ProductGroups")]
[Display(Name = "ProductProductGroupName")]
@ -37,7 +30,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewM
[Display(Name = "ProductDisplayName")]
public string DisplayName { get; set; }
public CreateEditProductDetailViewModel ProductDetail { get; set; }
public EditProductDetailViewModel ProductDetail { get; set; }
[Required]
[Placeholder("ProductAttributeNamesPlaceholder")]

28
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/ProductListFilterViewModel.cs

@ -0,0 +1,28 @@
using System;
using System.ComponentModel.DataAnnotations;
using EasyAbp.Abp.TagHelperPlus.EasySelector;
using EasyAbp.EShop.Stores;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewModels
{
public class ProductListFilterViewModel
{
[EasySelector(
getListedDataSourceUrl: StoresConsts.GetStoreListedDataSourceUrl + "?onlyManageable=true",
getSingleDataSourceUrl: StoresConsts.GetStoreSingleDataSourceUrl,
keyPropertyName: "id",
textPropertyName: "name",
runScriptOnWindowLoad: true)]
[Display(Name = "ProductStoreId")]
public Guid? StoreId { get; set; }
[EasySelector(
getListedDataSourceUrl: ProductsConsts.GetCategorySummaryListedDataSourceUrl,
getSingleDataSourceUrl: ProductsConsts.GetCategorySummarySingleDataSourceUrl,
keyPropertyName: "id",
textPropertyName: "displayName",
runScriptOnWindowLoad: true)]
[Display(Name = "ProductCategoryId")]
public Guid? CategoryId { get; set; }
}
}

14
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/index.js

@ -24,13 +24,13 @@ $(function () {
{
text: l('ProductSku'),
action: function (data) {
document.location.href = document.location.origin + '/EShop/Products/Products/ProductSku?ProductId=' + data.record.id + '&StoreId=' + storeId;
document.location.href = document.location.origin + '/EShop/Products/Products/ProductSku?ProductId=' + data.record.id;
}
},
{
text: l('Edit'),
action: function (data) {
editModal.open({ id: data.record.id, storeId: storeId });
editModal.open({ id: data.record.id });
}
},
{
@ -39,7 +39,7 @@ $(function () {
return l('ProductDeletionConfirmationMessage', data.record.id);
},
action: function (data) {
service.delete(data.record.id, storeId)
service.delete(data.record.id)
.then(function () {
abp.notify.info(l('SuccessfullyDeleted'));
dataTable.ajax.reload();
@ -70,4 +70,12 @@ $(function () {
e.preventDefault();
createModal.open({ storeId: storeId, categoryId: categoryId });
});
$('#enter-button').click(function (e) {
e.preventDefault();
var storeId = $('#Filter_StoreId').val();
var categoryId = $('#Filter_CategoryId').val();
document.location.href = document.location.origin + document.location.pathname + '?storeId=' + storeId + "&categoryId=" + categoryId;
})
});

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ChangeInventoryModal.cshtml

@ -13,7 +13,6 @@
<abp-modal-body>
<abp-input asp-for="ProductId" />
<abp-input asp-for="ProductSkuId" />
<abp-input asp-for="StoreId" />
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>

5
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ChangeInventoryModal.cshtml.cs

@ -16,10 +16,6 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductSkuId { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid StoreId { get; set; }
[BindProperty]
public ChangeProductInventoryViewModel ViewModel { get; set; }
@ -48,7 +44,6 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
{
ProductId = ProductId,
ProductSkuId = ProductSkuId,
StoreId = StoreId,
ChangedInventory = ViewModel.ProductInventoryChangeType == InventoryChangeType.IncreaseInventory
? ViewModel.ChangedInventory
: -ViewModel.ChangedInventory

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/CreateModal.cshtml

@ -11,7 +11,6 @@
<abp-modal>
<abp-modal-header title="@L["CreateProductSku"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="StoreId" />
<abp-input asp-for="ProductId" />
<abp-form-content/>
@foreach (var attr in Model.Attributes)

9
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/CreateModal.cshtml.cs

@ -14,10 +14,6 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
{
public class CreateModalModel : ProductsPageModel
{
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid StoreId { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductId { get; set; }
@ -43,7 +39,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public virtual async Task OnGetAsync()
{
var product = await _productAppService.GetAsync(ProductId, StoreId);
var product = await _productAppService.GetAsync(ProductId);
Attributes = new Dictionary<string, ICollection<SelectListItem>>();
@ -61,13 +57,12 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
createDto.AttributeOptionIds = SelectedAttributeOptionIdDict.Values.ToList();
var skuDto = await _productAppService.CreateSkuAsync(ProductId, StoreId, createDto);
var skuDto = await _productAppService.CreateSkuAsync(ProductId, createDto);
await _productInventoryAppService.UpdateAsync(new UpdateProductInventoryDto
{
ProductId = ProductId,
ProductSkuId = skuDto.Id,
StoreId = StoreId,
ChangedInventory = ProductSku.Inventory
});

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/EditModal.cshtml

@ -11,7 +11,6 @@
<abp-modal>
<abp-modal-header title="@L["EditProductSku"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="StoreId" />
<abp-input asp-for="ProductId" />
<abp-input asp-for="ProductSkuId" />
<abp-form-content />

8
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/EditModal.cshtml.cs

@ -12,10 +12,6 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
{
public class EditModalModel : ProductsPageModel
{
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid StoreId { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductId { get; set; }
@ -36,7 +32,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public virtual async Task OnGetAsync()
{
var product = await _productAppService.GetAsync(ProductId, StoreId);
var product = await _productAppService.GetAsync(ProductId);
ProductSku =
ObjectMapper.Map<ProductSkuDto, EditProductSkuViewModel>(
@ -45,7 +41,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public virtual async Task<IActionResult> OnPostAsync()
{
await _productAppService.UpdateSkuAsync(ProductId, ProductSkuId, StoreId,
await _productAppService.UpdateSkuAsync(ProductId, ProductSkuId,
ObjectMapper.Map<EditProductSkuViewModel, UpdateProductSkuDto>(ProductSku));
return NoContent();

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/Index.cshtml

@ -25,7 +25,6 @@
<abp-style src="/Pages/EShop/Products/Products/ProductSku/index.css"/>
}
<script>
let storeId = '@Model.StoreId';
let productId = '@Model.ProductId';
</script>

5
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/Index.cshtml.cs

@ -10,9 +10,6 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
{
private readonly IProductAppService _productAppService;
[BindProperty(SupportsGet = true)]
public Guid StoreId { get; set; }
[BindProperty(SupportsGet = true)]
public Guid ProductId { get; set; }
@ -25,7 +22,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public virtual async Task OnGetAsync()
{
ProductDisplayName = (await _productAppService.GetAsync(ProductId, StoreId)).DisplayName;
ProductDisplayName = (await _productAppService.GetAsync(ProductId)).DisplayName;
}
}
}

10
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/index.js

@ -14,7 +14,7 @@ $(function () {
order: [[1, "asc"]],
ajax: function (requestData, callback, settings) {
if (callback) {
service.get(productId, storeId).then(function (result) {
service.get(productId).then(function (result) {
callback({
recordsTotal: result.productSkus.length,
recordsFiltered: result.productSkus.length,
@ -32,14 +32,14 @@ $(function () {
text: l('Edit'),
visible: abp.auth.isGranted('EasyAbp.EShop.Products.Product.Update'),
action: function (data) {
editModal.open({ productId: productId, productSkuId: data.record.id, storeId: storeId });
editModal.open({ productId: productId, productSkuId: data.record.id });
}
},
{
text: l('ProductInventory'),
visible: abp.auth.isGranted('EasyAbp.EShop.Products.ProductInventory.Update'),
action: function (data) {
changeInventoryModal.open({ productId: productId, productSkuId: data.record.id, storeId: storeId });
changeInventoryModal.open({ productId: productId, productSkuId: data.record.id });
}
},
{
@ -49,7 +49,7 @@ $(function () {
return l('ProductDeletionConfirmationMessage', data.record.id);
},
action: function (data) {
service.deleteSku(productId, data.record.id, storeId)
service.deleteSku(productId, data.record.id)
.then(function () {
abp.notify.info(l('SuccessfullyDeleted'));
dataTable.ajax.reload();
@ -81,7 +81,7 @@ $(function () {
$('#NewProductSkuButton').click(function (e) {
e.preventDefault();
createModal.open({ storeId: storeId, productId: productId });
createModal.open({ productId: productId });
});
function fillProductSkusContentDescription(product) {

29
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/ProductsWebAutoMapperProfile.cs

@ -19,10 +19,9 @@ namespace EasyAbp.EShop.Products.Web
/* You can configure your AutoMapper mapping configuration here.
* Alternatively, you can split your mapping configurations
* into multiple profile classes for a better organization. */
CreateMap<ProductDto, CreateEditProductViewModel>()
CreateMap<ProductDto, EditProductViewModel>()
.Ignore(model => model.CategoryIds)
.Ignore(model => model.ProductDetail)
.Ignore(model => model.StoreId)
.ForSourceMember(dto => dto.Sold, opt => opt.DoNotValidate())
.ForSourceMember(dto => dto.ProductDetailId, opt => opt.DoNotValidate())
// .Ignore(x => x.ProductAttributes);
@ -34,7 +33,7 @@ namespace EasyAbp.EShop.Products.Web
x.ProductAttributes
.Select(a => a.ProductAttributeOptions.Select(o => o.DisplayName).JoinAsString(","))
.JoinAsString(Environment.NewLine)));
CreateMap<CreateEditProductViewModel, CreateUpdateProductDto>()
CreateMap<CreateProductViewModel, CreateUpdateProductDto>()
.Ignore(dto => dto.ExtraProperties)
.Ignore(dto => dto.ProductDetailId)
.ForSourceMember(model => model.ProductDetail, opt => opt.DoNotValidate())
@ -49,9 +48,27 @@ namespace EasyAbp.EShop.Products.Web
.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(o =>
new CreateUpdateProductAttributeOptionDto {DisplayName = o}))
})));
CreateMap<ProductDetailDto, CreateEditProductDetailViewModel>()
.Ignore(model => model.StoreId);
CreateMap<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>()
CreateMap<EditProductViewModel, CreateUpdateProductDto>()
.Ignore(dto => dto.StoreId)
.Ignore(dto => dto.ExtraProperties)
.Ignore(dto => dto.ProductDetailId)
.ForSourceMember(model => model.ProductDetail, opt => opt.DoNotValidate())
.ForMember(dest => dest.ProductAttributes,
opt => opt.MapFrom(x =>
x.ProductAttributeNames.Split(",", StringSplitOptions.RemoveEmptyEntries).Select((s, i) =>
new CreateUpdateProductAttributeDto
{
DisplayName = s,
ProductAttributeOptions = new List<CreateUpdateProductAttributeOptionDto>(
x.ProductAttributeOptionNames.SplitToLines(StringSplitOptions.RemoveEmptyEntries)[i]
.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(o =>
new CreateUpdateProductAttributeOptionDto {DisplayName = o}))
})));
CreateMap<ProductDetailDto, CreateProductDetailViewModel>();
CreateMap<CreateProductDetailViewModel, CreateUpdateProductDetailDto>()
.Ignore(dto => dto.ExtraProperties);
CreateMap<EditProductDetailViewModel, CreateUpdateProductDetailDto>()
.Ignore(dto => dto.StoreId)
.Ignore(dto => dto.ExtraProperties);
CreateMap<ProductAttributeDto, CreateEditProductAttributeViewModel>();
CreateMap<CreateEditProductAttributeViewModel, CreateUpdateProductAttributeDto>()

2
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductAppServiceTests.cs

@ -99,7 +99,7 @@ namespace EasyAbp.EShop.Products.Products
productAttributeOptionId = productAttribute.ProductAttributeOptions.First().Id;
});
var response = await _productAppService.CreateSkuAsync(productId, ProductsTestData.Store1Id, new CreateProductSkuDto
var response = await _productAppService.CreateSkuAsync(productId, new CreateProductSkuDto
{
AttributeOptionIds = new List<Guid> {productAttributeOptionId},
Currency = "CNY",

23
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Domain.Tests/ProductStores/ProductStoreDomainTests.cs

@ -1,23 +0,0 @@
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace EasyAbp.EShop.Products.ProductStores
{
public class ProductStoreDomainTests : ProductsDomainTestBase
{
public ProductStoreDomainTests()
{
}
[Fact]
public async Task Test1()
{
// Arrange
// Assert
// Assert
}
}
}

31
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductStores/ProductStoreRepositoryTests.cs

@ -1,31 +0,0 @@
using System;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductStores;
using Volo.Abp.Domain.Repositories;
using Xunit;
namespace EasyAbp.EShop.Products.EntityFrameworkCore.ProductStores
{
public class ProductStoreRepositoryTests : ProductsEntityFrameworkCoreTestBase
{
private readonly IRepository<ProductStore, Guid> _productStoreRepository;
public ProductStoreRepositoryTests()
{
_productStoreRepository = GetRequiredService<IRepository<ProductStore, Guid>>();
}
[Fact]
public async Task Test1()
{
await WithUnitOfWorkAsync(async () =>
{
// Arrange
// Act
//Assert
});
}
}
}

3
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.TestBase/ProductsTestDataBuilder.cs

@ -21,7 +21,8 @@ namespace EasyAbp.EShop.Products
public async Task BuildAsync()
{
await _productDetailRepository.InsertAsync(new ProductDetail(ProductsTestData.ProductDetails1Id, "Product Details"));
await _productDetailRepository.InsertAsync(new ProductDetail(ProductsTestData.ProductDetails1Id,
ProductsTestData.Store1Id, "Product details for store 1"));
}
}
}

2
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/StoreOwners/Dtos/StoreOwnerDto.cs

@ -11,5 +11,7 @@ namespace EasyAbp.EShop.Stores.StoreOwners.Dtos
public Guid StoreId { get; set; }
public Guid OwnerUserId { get; set; }
public string OwnerUserName { get; set; }
}
}

13
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Stores/Dtos/GetStoreListInput.cs

@ -0,0 +1,13 @@
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Stores.Stores.Dtos
{
public class GetStoreListInput : PagedAndSortedResultRequestDto
{
/// <summary>
/// Store owner users can get stores that they owns.
/// Users who have the <code>EasyAbp.EShop.Stores.Store.CrossStore</code> permission can get all stores.
/// </summary>
public bool OnlyManageable { get; set; }
}
}

2
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application.Contracts/EasyAbp/EShop/Stores/Stores/IStoreAppService.cs

@ -10,7 +10,7 @@ namespace EasyAbp.EShop.Stores.Stores
ICrudAppService<
StoreDto,
Guid,
PagedAndSortedResultRequestDto,
GetStoreListInput,
CreateUpdateStoreDto,
CreateUpdateStoreDto>
{

1
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp.EShop.Stores.Application.csproj

@ -10,6 +10,7 @@
<ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Users.Abstractions" Version="$(AbpVersion)" />
<ProjectReference Include="..\EasyAbp.EShop.Stores.Application.Contracts\EasyAbp.EShop.Stores.Application.Contracts.csproj" />
<ProjectReference Include="..\EasyAbp.EShop.Stores.Application.Shared\EasyAbp.EShop.Stores.Application.Shared.csproj" />
<ProjectReference Include="..\EasyAbp.EShop.Stores.Domain\EasyAbp.EShop.Stores.Domain.csproj" />

4
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/EShopStoresApplicationModule.cs

@ -2,6 +2,7 @@
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.Application;
using Volo.Abp.Users;
namespace EasyAbp.EShop.Stores
{
@ -10,8 +11,9 @@ namespace EasyAbp.EShop.Stores
typeof(EShopStoresApplicationSharedModule),
typeof(EShopStoresApplicationContractsModule),
typeof(AbpDddApplicationModule),
typeof(AbpUsersAbstractionModule),
typeof(AbpAutoMapperModule)
)]
)]
public class EShopStoresApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

42
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoreOwners/StoreOwnerAppService.cs

@ -4,6 +4,8 @@ using System.Threading.Tasks;
using EasyAbp.EShop.Stores.Permissions;
using EasyAbp.EShop.Stores.StoreOwners.Dtos;
using EasyAbp.EShop.Stores.Stores;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Users;
namespace EasyAbp.EShop.Stores.StoreOwners
{
@ -18,10 +20,15 @@ namespace EasyAbp.EShop.Stores.StoreOwners
protected override string CrossStorePolicyName { get; set; } = StoresPermissions.Stores.CrossStore;
private readonly IStoreOwnerRepository _repository;
private readonly IExternalUserLookupServiceProvider _externalUserLookupServiceProvider;
public StoreOwnerAppService(IStoreOwnerRepository repository) : base(repository)
public StoreOwnerAppService(
IStoreOwnerRepository repository,
IExternalUserLookupServiceProvider externalUserLookupServiceProvider)
: base(repository)
{
_repository = repository;
_externalUserLookupServiceProvider = externalUserLookupServiceProvider;
}
public override async Task<StoreOwnerDto> CreateAsync(CreateUpdateStoreOwnerDto input)
@ -33,7 +40,38 @@ namespace EasyAbp.EShop.Stores.StoreOwners
return await base.CreateAsync(input);
}
public override async Task<StoreOwnerDto> GetAsync(Guid id)
{
var dto = await base.GetAsync(id);
var userData = await _externalUserLookupServiceProvider.FindByIdAsync(dto.OwnerUserId);
if (userData != null)
{
dto.OwnerUserName = userData.UserName;
}
return dto;
}
public override async Task<PagedResultDto<StoreOwnerDto>> GetListAsync(GetStoreOwnerListDto input)
{
var result = await base.GetListAsync(input);
foreach (var dto in result.Items)
{
var userData = await _externalUserLookupServiceProvider.FindByIdAsync(dto.OwnerUserId);
if (userData != null)
{
dto.OwnerUserName = userData.UserName;
}
}
return result;
}
protected override IQueryable<StoreOwner> CreateFilteredQuery(GetStoreOwnerListDto input)
{
var queryable = Repository.AsQueryable();

43
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/Stores/StoreAppService.cs

@ -1,15 +1,16 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Stores.Permissions;
using EasyAbp.EShop.Stores.Stores.Dtos;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Users;
namespace EasyAbp.EShop.Stores.Stores
{
public class StoreAppService : CrudAppService<Store, StoreDto, Guid, PagedAndSortedResultRequestDto,
CreateUpdateStoreDto, CreateUpdateStoreDto>,
IStoreAppService
public class StoreAppService : CrudAppService<Store, StoreDto, Guid, GetStoreListInput, CreateUpdateStoreDto, CreateUpdateStoreDto>, IStoreAppService
{
protected override string CreatePolicyName { get; set; } = StoresPermissions.Stores.Create;
protected override string DeletePolicyName { get; set; } = StoresPermissions.Stores.Delete;
@ -17,13 +18,47 @@ namespace EasyAbp.EShop.Stores.Stores
protected override string GetPolicyName { get; set; } = StoresPermissions.Stores.Default;
protected override string GetListPolicyName { get; set; } = StoresPermissions.Stores.Default;
private readonly IPermissionChecker _permissionChecker;
private readonly IStoreRepository _repository;
public StoreAppService(IStoreRepository repository) : base(repository)
public StoreAppService(
IPermissionChecker permissionChecker,
IStoreRepository repository) : base(repository)
{
_permissionChecker = permissionChecker;
_repository = repository;
}
protected virtual async Task<IQueryable<Store>> CreateFilteredQueryAsync(GetStoreListInput input)
{
if (!input.OnlyManageable || await _permissionChecker.IsGrantedAsync(StoresPermissions.Stores.CrossStore))
{
return _repository.AsQueryable();
}
return _repository.GetQueryableOnlyOwnStore(CurrentUser.GetId());
}
public override async Task<PagedResultDto<StoreDto>> GetListAsync(GetStoreListInput input)
{
await CheckGetListPolicyAsync();
var query = await CreateFilteredQueryAsync(input);
var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
var entities = await AsyncExecuter.ToListAsync(query);
var entityDtos = await MapToGetListOutputDtosAsync(entities);
return new PagedResultDto<StoreDto>(
totalCount,
entityDtos
);
}
public async Task<StoreDto> GetDefaultAsync()
{
// Todo: need to be improved

4
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Application/EasyAbp/EShop/Stores/StoresApplicationAutoMapperProfile.cs

@ -5,6 +5,7 @@ using EasyAbp.EShop.Stores.Stores;
using EasyAbp.EShop.Stores.Stores.Dtos;
using EasyAbp.EShop.Stores.Transactions;
using EasyAbp.EShop.Stores.Transactions.Dtos;
using Volo.Abp.AutoMapper;
using Volo.Abp.ObjectExtending;
namespace EasyAbp.EShop.Stores
@ -19,7 +20,8 @@ namespace EasyAbp.EShop.Stores
CreateMap<Store, StoreDto>();
CreateMap<CreateUpdateStoreDto, Store>(MemberList.Source);
CreateMap<StoreOwner, StoreOwnerDto>();
CreateMap<StoreOwner, StoreOwnerDto>()
.Ignore(dto => dto.OwnerUserName);
CreateMap<CreateUpdateStoreOwnerDto, StoreOwner>(MemberList.Source);
CreateMap<Transaction, TransactionDto>();

6
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain.Shared/EasyAbp/EShop/Stores/StoresConsts.cs

@ -5,5 +5,11 @@
public const string TransactionOrderCompletedActionName = "OrderCompleted";
public const string TransactionOrderRefundedActionName = "OrderRefunded";
public const string StoreRouteBase = "/api/e-shop/stores/store";
public const string GetStoreListedDataSourceUrl = StoreRouteBase;
public const string GetStoreSingleDataSourceUrl = StoreRouteBase + "/{id}";
}
}

3
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Domain/EasyAbp/EShop/Stores/Stores/IStoreRepository.cs

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -8,5 +9,7 @@ namespace EasyAbp.EShop.Stores.Stores
public interface IStoreRepository : IRepository<Store, Guid>
{
Task<Store> FindDefaultStoreAsync(CancellationToken cancellationToken = default);
IQueryable<Store> GetQueryableOnlyOwnStore(Guid userId);
}
}

11
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.EntityFrameworkCore/EasyAbp/EShop/Stores/Stores/StoreRepository.cs

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EasyAbp.EShop.Stores.EntityFrameworkCore;
@ -18,5 +19,15 @@ namespace EasyAbp.EShop.Stores.Stores
{
return await WithDetails().FirstOrDefaultAsync(cancellationToken: cancellationToken);
}
public virtual IQueryable<Store> GetQueryableOnlyOwnStore(Guid userId)
{
return DbSet.Join(
DbContext.StoreOwners.Where(storeOwner => storeOwner.OwnerUserId == userId),
store => store.Id,
storeOwner => storeOwner.StoreId,
(store, storeOwner) => store
);
}
}
}

4
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.HttpApi/EasyAbp/EShop/Stores/Stores/StoreController.cs

@ -8,7 +8,7 @@ using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Stores.Stores
{
[RemoteService(Name = "EasyAbpEShopStores")]
[Route("/api/e-shop/stores/store")]
[Route(StoresConsts.StoreRouteBase)]
public class StoreController : StoresController, IStoreAppService
{
private readonly IStoreAppService _service;
@ -26,7 +26,7 @@ namespace EasyAbp.EShop.Stores.Stores
}
[HttpGet]
public Task<PagedResultDto<StoreDto>> GetListAsync(PagedAndSortedResultRequestDto input)
public Task<PagedResultDto<StoreDto>> GetListAsync(GetStoreListInput input)
{
return _service.GetListAsync(input);
}

8
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EShopStoresWebModule.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using EasyAbp.Abp.TagHelperPlus;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
using EasyAbp.EShop.Stores.Localization;
using EasyAbp.EShop.Stores.Web.Menus;
@ -16,8 +17,9 @@ namespace EasyAbp.EShop.Stores.Web
typeof(EShopStoresHttpApiModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule),
typeof(AbpAutoMapperModule),
typeof(AbpIdentityApplicationContractsModule)
)]
typeof(AbpIdentityApplicationContractsModule),
typeof(AbpTagHelperPlusModule)
)]
public class EShopStoresWebModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)

1
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/EasyAbp.EShop.Stores.Web.csproj

@ -12,6 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EasyAbp.Abp.TagHelperPlus" Version="0.6.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Identity.Application.Contracts" Version="$(AbpVersion)" />

12
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/Index.js

@ -4,7 +4,6 @@ $(function () {
var service = easyAbp.eShop.stores.storeOwners.storeOwner;
var storeService = easyAbp.eShop.stores.stores.store;
var userService = volo.abp.identity.identityUser;
var createModal = new abp.ModalManager(abp.appPath + 'EShop/Stores/StoreOwners/StoreOwner/CreateModal');
var editModal = new abp.ModalManager(abp.appPath + 'EShop/Stores/StoreOwners/StoreOwner/EditModal');
@ -58,16 +57,7 @@ $(function () {
}
},
{
data: "ownerUserId",
render: function (data, type, row, meta) {
var currentCell = $("#StoreOwnerTable").DataTable().cells({"row":meta.row, "column":meta.col}).nodes(0);
userService.get(data).then(
x=>{
$(currentCell).html(x.userName);
}
);
return '...';
}
data: "ownerUserName"
}
]
}));

17
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/StoreOwners/StoreOwner/ViewModels/CreateStoreOwnerViewModel.cs

@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using EasyAbp.Abp.TagHelperPlus.EasySelector;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.ObjectExtending;
@ -7,11 +8,21 @@ namespace EasyAbp.EShop.Stores.Web.Pages.EShop.Stores.StoreOwners.StoreOwner.Vie
{
public class CreateEditStoreOwnerViewModel
{
[Required]
[EasySelector(
getListedDataSourceUrl: StoresConsts.GetStoreListedDataSourceUrl + "?onlyManageable=true",
getSingleDataSourceUrl: StoresConsts.GetStoreSingleDataSourceUrl,
keyPropertyName: "id",
textPropertyName: "name")]
[Display(Name = "StoreOwnerStoreId")]
public Guid StoreId { get; set; }
[Required]
[EasySelector(
getListedDataSourceUrl: "/api/identity/users",
getSingleDataSourceUrl: "/api/identity/users/{id}",
keyPropertyName: "id",
textPropertyName: "name",
alternativeTextPropertyName: "userName")]
[Display(Name = "StoreOwnerOwnerUserId")]
public Guid OwnerUserId { get; set; }
}
}

2
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs

@ -16,8 +16,6 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos
/// </summary>
public Guid? UserId { get; set; }
public Guid StoreId { get; set; }
public Guid ProductId { get; set; }
public Guid ProductSkuId { get; set; }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save