Browse Source

Merge branch 'dev' of https://github.com/EasyAbp/EShop into dev

pull/87/head
gdlcf88 6 years ago
parent
commit
135c548d36
  1. 2
      common.props
  2. 7
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs
  3. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/ProductInventoryDto.cs
  4. 3
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/CreateUpdateProductDto.cs
  5. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/CreateUpdateProductSkuDto.cs
  6. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductDto.cs
  7. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs
  8. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs
  9. 31
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
  10. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
  11. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/cs.json
  12. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
  13. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pl.json
  14. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pt-BR.json
  15. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/sl.json
  16. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/tr.json
  17. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/vi.json
  18. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
  19. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
  20. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductInventories/ProductInventoryChangedEto.cs
  21. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/IProductInventoryRepository.cs
  22. 24
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/ProductInventory.cs
  23. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ConsumeInventoryModel.cs
  24. 37
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductInventoryProvider.cs
  25. 11
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountManager.cs
  26. 10
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductInventoryProvider.cs
  27. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductManager.cs
  28. 9
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/InventoryDataModel.cs
  29. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderCreatedEventHandler.cs
  30. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderPaidEventHandler.cs
  31. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/Product.cs
  32. 22
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductDiscountManager.cs
  33. 54
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs
  34. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductSku.cs
  35. 22
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/ProductInventories/ProductInventoryRepository.cs
  36. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml
  37. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateEditProductViewModel.cs
  38. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/index.js
  39. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/Index.cshtml
  40. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/EditProductSkuViewModel.cs
  41. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/index.js
  42. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/ProductsWebAutoMapperProfile.cs
  43. 3837
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706060054_AddedSpecifiedInventoryProviderName.Designer.cs
  44. 31
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706060054_AddedSpecifiedInventoryProviderName.cs
  45. 3837
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706070250_ChangedSoldToLong.Designer.cs
  46. 27
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706070250_ChangedSoldToLong.cs
  47. 10
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/EShopSampleMigrationsDbContextModelSnapshot.cs

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.3.8</Version>
<Version>0.4.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>EasyAbp Team</Authors>

7
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs

@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Orders.Orders.Dtos;
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos;
using Volo.Abp.DependencyInjection;
@ -75,6 +76,12 @@ namespace EasyAbp.EShop.Orders.Orders
{
throw new OrderLineInvalidQuantityException(product.Id, productSku.Id, input.Quantity);
}
if (productSku.Inventory < input.Quantity)
{
throw new InventoryInsufficientException(input.ProductId, input.ProductSkuId, input.Quantity,
productSku.Inventory);
}
return new OrderLine(
id: _guidGenerator.Create(),

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

@ -12,6 +12,6 @@ namespace EasyAbp.EShop.Products.ProductInventories.Dtos
public int Inventory { get; set; }
public int Sold { get; set; }
public long Sold { get; set; }
}
}

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

@ -41,6 +41,9 @@ namespace EasyAbp.EShop.Products.Products.Dtos
[DisplayName("ProductMediaResources")]
public string MediaResources { get; set; }
[DisplayName("ProductSpecifiedInventoryProviderName")]
public string SpecifiedInventoryProviderName { get; set; }
[DisplayName("ProductIsPublished")]
public bool IsPublished { get; set; }

6
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/CreateUpdateProductSkuDto.cs

@ -27,6 +27,12 @@ namespace EasyAbp.EShop.Products.Products.Dtos
[DefaultValue(99)]
[DisplayName("ProductSkuOrderMaxQuantity")]
public int OrderMaxQuantity { get; set; }
[DisplayName("ProductSkuMediaResources")]
public string MediaResources { get; set; }
[DisplayName("ProductSkuSpecifiedInventoryProviderName")]
public string SpecifiedInventoryProviderName { get; set; }
[DisplayName("ProductSkuProductDetailId")]
public Guid? ProductDetailId { get; set; }

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

@ -20,6 +20,8 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public string MediaResources { get; set; }
public string SpecifiedInventoryProviderName { get; set; }
public int DisplayOrder { get; set; }
public bool IsPublished { get; set; }
@ -28,6 +30,8 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public bool IsHidden { get; set; }
public long Sold { get; set; }
public decimal? MinimumPrice { get; set; }
public decimal? MaximumPrice { get; set; }

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

@ -19,14 +19,11 @@ namespace EasyAbp.EShop.Products.Products.Dtos
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// Price from IProductDiscountManager
/// </summary>
public decimal DiscountedPrice { get; set; }
public int Inventory { get; set; }
public int Sold { get; set; }
public long Sold { get; set; }
public int OrderMinQuantity { get; set; }
@ -34,6 +31,8 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public string MediaResources { get; set; }
public string SpecifiedInventoryProviderName { get; set; }
public Guid? ProductDetailId { get; set; }
}
}

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

@ -81,7 +81,7 @@ namespace EasyAbp.EShop.Products.ProductInventories
{
if (changedInventory >= 0)
{
if (!await _productInventoryProvider.TryIncreaseInventoryAsync(productInventory, changedInventory))
if (!await _productInventoryProvider.TryIncreaseInventoryAsync(productInventory, changedInventory, false))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);
@ -89,7 +89,7 @@ namespace EasyAbp.EShop.Products.ProductInventories
}
else
{
if (!await _productInventoryProvider.TryReduceInventoryAsync(productInventory, -changedInventory))
if (!await _productInventoryProvider.TryReduceInventoryAsync(productInventory, -changedInventory, false))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);

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

@ -23,7 +23,6 @@ namespace EasyAbp.EShop.Products.Products
protected override string GetListPolicyName { get; set; } = null;
private readonly IProductManager _productManager;
private readonly IProductDiscountManager _productDiscountManager;
private readonly IProductInventoryProvider _productInventoryProvider;
private readonly IAttributeOptionIdsSerializer _attributeOptionIdsSerializer;
private readonly IProductStoreRepository _productStoreRepository;
@ -31,14 +30,12 @@ namespace EasyAbp.EShop.Products.Products
public ProductAppService(
IProductManager productManager,
IProductDiscountManager productDiscountManager,
IProductInventoryProvider productInventoryProvider,
IAttributeOptionIdsSerializer attributeOptionIdsSerializer,
IProductStoreRepository productStoreRepository,
IProductRepository repository) : base(repository)
{
_productManager = productManager;
_productDiscountManager = productDiscountManager;
_productInventoryProvider = productInventoryProvider;
_attributeOptionIdsSerializer = attributeOptionIdsSerializer;
_productStoreRepository = productStoreRepository;
@ -202,8 +199,8 @@ namespace EasyAbp.EShop.Products.Products
var dto = MapToGetOutputDto(product);
await LoadRealInventoriesAsync(product, dto, storeId);
await LoadPricesAsync(product, dto, storeId);
await LoadDtoInventoryDataAsync(product, dto, storeId);
await LoadDtoPriceAsync(product, dto, storeId);
return dto;
}
@ -221,7 +218,7 @@ namespace EasyAbp.EShop.Products.Products
var dto = MapToGetOutputDto(product);
await LoadRealInventoriesAsync(product, dto, storeId);
await LoadDtoInventoryDataAsync(product, dto, storeId);
return dto;
}
@ -259,8 +256,8 @@ namespace EasyAbp.EShop.Products.Products
{
var productDto = MapToGetListOutputDto(product);
await LoadRealInventoriesAsync(product, productDto, input.StoreId);
await LoadPricesAsync(product, productDto, input.StoreId);
await LoadDtoInventoryDataAsync(product, productDto, input.StoreId);
await LoadDtoPriceAsync(product, productDto, input.StoreId);
items.Add(productDto);
}
@ -268,23 +265,29 @@ namespace EasyAbp.EShop.Products.Products
return new PagedResultDto<ProductDto>(totalCount, items);
}
protected virtual async Task<ProductDto> LoadRealInventoriesAsync(Product product, ProductDto productDto, Guid storeId)
protected virtual async Task<ProductDto> LoadDtoInventoryDataAsync(Product product, ProductDto productDto, Guid storeId)
{
var inventoryDict = await _productInventoryProvider.GetInventoryDictionaryAsync(product, storeId);
var inventoryDataDict = await _productInventoryProvider.GetInventoryDataDictionaryAsync(product, storeId);
productDto.Sold = 0;
foreach (var productSkuDto in productDto.ProductSkus)
{
productSkuDto.Inventory = inventoryDict[productSkuDto.Id];
var inventoryData = inventoryDataDict[productSkuDto.Id];
productSkuDto.Inventory = inventoryData.Inventory;
productSkuDto.Sold = inventoryData.Sold;
productDto.Sold += productSkuDto.Sold;
}
return productDto;
}
protected virtual async Task<ProductDto> LoadPricesAsync(Product product, ProductDto productDto, Guid storeId)
protected virtual async Task<ProductDto> LoadDtoPriceAsync(Product product, ProductDto productDto, Guid storeId)
{
foreach (var productSkuDto in productDto.ProductSkus)
{
productSkuDto.DiscountedPrice = await _productDiscountManager.GetDiscountedPriceAsync(product,
productSkuDto.DiscountedPrice = await _productManager.GetDiscountedPriceAsync(product,
product.ProductSkus.Single(sku => sku.Id == productSkuDto.Id), storeId);
}
@ -372,7 +375,5 @@ namespace EasyAbp.EShop.Products.Products
return ObjectMapper.Map<Product, ProductDto>(product);
}
}
}

1
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs

@ -29,6 +29,7 @@ namespace EasyAbp.EShop.Products
* Alternatively, you can split your mapping configurations
* into multiple profile classes for a better organization. */
CreateMap<Product, ProductDto>()
.Ignore(dto => dto.Sold)
.Ignore(dto => dto.MinimumPrice)
.Ignore(dto => dto.MaximumPrice);
CreateMap<ProductDetail, ProductDetailDto>();

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

@ -1,6 +1,7 @@
{
"culture": "cs",
"texts": {
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -26,9 +27,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -37,6 +40,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -84,7 +88,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -2,6 +2,7 @@
"culture": "en",
"texts": {
"ManageYourProfile": "Manage your profile",
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -27,9 +28,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -38,6 +41,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -85,7 +89,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -1,6 +1,7 @@
{
"culture": "pl",
"texts": {
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -26,9 +27,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -37,6 +40,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -84,7 +88,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -1,6 +1,7 @@
{
"culture": "pt-BR",
"texts": {
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -26,9 +27,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -37,6 +40,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -84,7 +88,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -2,6 +2,7 @@
"culture": "sl",
"texts": {
"ManageYourProfile": "Upravljajte svojim profilom",
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -27,9 +28,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -38,6 +41,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -85,7 +89,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -2,6 +2,7 @@
"culture": "tr",
"texts": {
"ManageYourProfile": "Profil y�netimi",
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -27,9 +28,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -38,6 +41,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -85,7 +89,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -1,6 +1,7 @@
{
"culture": "vi",
"texts": {
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -26,9 +27,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -37,6 +40,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -84,7 +88,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -2,6 +2,7 @@
"culture": "zh-Hans",
"texts": {
"ManageYourProfile": "管理个人资料",
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -27,9 +28,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -38,6 +41,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -85,7 +89,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -2,6 +2,7 @@
"culture": "zh-Hant",
"texts": {
"ManageYourProfile": "管理個人資料",
"KeepEmptyIfDoNotKnow": "KeepEmptyIfDoNotKnow",
"Menu:Product": "MenuProduct",
"Product": "Product",
"ProductStore": "ProductStore",
@ -27,9 +28,11 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",
"ProductSkuSpecifiedInventoryProviderName": "ProductSkuSpecifiedInventoryProviderName",
"ProductSkuProductDetailId": "ProductSkuProductDetailId",
"ProductSkuContentDescription": "ProductSkuContentDescription",
"CreateProductSku": "CreateProductSku",
@ -38,6 +41,7 @@
"ProductInventoryStrategy": "ProductInventoryStrategy",
"ProductIsPublished": "ProductIsPublished",
"ProductMediaResources": "ProductMediaResources",
"ProductSpecifiedInventoryProviderName": "ProductSpecifiedInventoryProviderName",
"ProductAttributeDisplayName": "ProductAttributeDisplayName",
"ProductAttributeDescription": "ProductAttributeDescription",
"ProductAttributeDisplayOrder": "ProductAttributeDisplayOrder",
@ -85,7 +89,6 @@
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductInventories/ProductInventoryChangedEto.cs

@ -12,5 +12,7 @@ namespace EasyAbp.EShop.Products.ProductInventories
public int OriginalInventory { get; set; }
public int NewInventory { get; set; }
public long Sold { get; set; }
}
}

5
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/IProductInventoryRepository.cs

@ -2,14 +2,15 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Products;
using Volo.Abp.Domain.Repositories;
namespace EasyAbp.EShop.Products.ProductInventories
{
public interface IProductInventoryRepository : IRepository<ProductInventory, Guid>
{
Task<int> GetInventoryAsync(Guid productSkuId, CancellationToken cancellationToken = default);
Task<InventoryDataModel> GetInventoryDataAsync(Guid productSkuId, CancellationToken cancellationToken = default);
Task<Dictionary<Guid, int>> GetInventoryDictionaryAsync(List<Guid> productSkuIds, CancellationToken cancellationToken = default);
Task<Dictionary<Guid, InventoryDataModel>> GetInventoryDataDictionaryAsync(List<Guid> productSkuIds, CancellationToken cancellationToken = default);
}
}

24
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/ProductInventory.cs

@ -11,8 +11,7 @@ namespace EasyAbp.EShop.Products.ProductInventories
public virtual int Inventory { get; protected set; }
// Todo: should be implemented
public virtual int Sold { get; protected set; }
public virtual long Sold { get; protected set; }
protected ProductInventory()
{
@ -23,7 +22,7 @@ namespace EasyAbp.EShop.Products.ProductInventories
Guid productId,
Guid productSkuId,
int inventory,
int sold) : base(id)
long sold) : base(id)
{
ProductId = productId;
ProductSkuId = productSkuId;
@ -31,19 +30,29 @@ namespace EasyAbp.EShop.Products.ProductInventories
Sold = sold;
}
internal bool TryIncreaseInventory(int quantity)
internal bool TryIncreaseInventory(int quantity, bool decreaseSold)
{
if (quantity < 0)
{
return false;
}
if (decreaseSold && Sold - quantity < 0)
{
return false;
}
Inventory = checked(Inventory + quantity);
if (decreaseSold)
{
Sold -= quantity;
}
return true;
}
internal bool TryReduceInventory(int quantity)
internal bool TryReduceInventory(int quantity, bool increaseSold)
{
if (quantity > Inventory || quantity < 0)
{
@ -51,6 +60,11 @@ namespace EasyAbp.EShop.Products.ProductInventories
}
Inventory -= quantity;
if (increaseSold)
{
Sold = checked(Sold + quantity);
}
return true;
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ReduceInventoryModel.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ConsumeInventoryModel.cs

@ -2,7 +2,7 @@
namespace EasyAbp.EShop.Products.Products
{
public class ReduceInventoryModel
public class ConsumeInventoryModel
{
public Product Product { get; set; }

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

@ -11,6 +11,8 @@ namespace EasyAbp.EShop.Products.Products
{
public class DefaultProductInventoryProvider : IProductInventoryProvider, ITransientDependency
{
public string ProviderName { get; } = "Default";
// Todo: should use IProductInventoryStore.
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IDistributedEventBus _distributedEventBus;
@ -26,39 +28,39 @@ namespace EasyAbp.EShop.Products.Products
_productInventoryRepository = productInventoryRepository;
}
public virtual async Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId)
public virtual async Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId)
{
return await _productInventoryRepository.GetInventoryAsync(productSku.Id);
return await _productInventoryRepository.GetInventoryDataAsync(productSku.Id);
}
public virtual async Task<Dictionary<Guid, int>> GetInventoryDictionaryAsync(Product product, Guid storeId)
public virtual async Task<Dictionary<Guid, InventoryDataModel>> GetInventoryDataDictionaryAsync(Product product, Guid storeId)
{
var dict = await _productInventoryRepository.GetInventoryDictionaryAsync(product.ProductSkus
var dict = await _productInventoryRepository.GetInventoryDataDictionaryAsync(product.ProductSkus
.Select(sku => sku.Id).ToList());
foreach (var sku in product.ProductSkus)
{
dict.GetOrAdd(sku.Id, () => 0);
dict.GetOrAdd(sku.Id, () => new InventoryDataModel());
}
return dict;
}
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool decreaseSold)
{
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);
return await TryIncreaseInventoryAsync(productInventory, quantity);
return await TryIncreaseInventoryAsync(productInventory, quantity, decreaseSold);
}
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool increaseSold)
{
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);
return await TryReduceInventoryAsync(productInventory, quantity);
return await TryReduceInventoryAsync(productInventory, quantity, increaseSold);
}
public virtual async Task<bool> TryIncreaseInventoryAsync(ProductInventory productInventory, int quantity)
public virtual async Task<bool> TryIncreaseInventoryAsync(ProductInventory productInventory, int quantity, bool decreaseSold)
{
if (quantity < 0)
{
@ -67,7 +69,7 @@ namespace EasyAbp.EShop.Products.Products
var originalInventory = productInventory.Inventory;
if (!productInventory.TryIncreaseInventory(quantity))
if (!productInventory.TryIncreaseInventory(quantity, decreaseSold))
{
return false;
}
@ -75,12 +77,12 @@ namespace EasyAbp.EShop.Products.Products
await _productInventoryRepository.UpdateAsync(productInventory, true);
PublishInventoryChangedEventOnUowCompleted(productInventory.ProductId, productInventory.ProductSkuId,
originalInventory, productInventory.Inventory);
originalInventory, productInventory.Inventory, productInventory.Sold);
return true;
}
public virtual async Task<bool> TryReduceInventoryAsync(ProductInventory productInventory, int quantity)
public virtual async Task<bool> TryReduceInventoryAsync(ProductInventory productInventory, int quantity, bool increaseSold)
{
if (quantity < 0)
{
@ -89,7 +91,7 @@ namespace EasyAbp.EShop.Products.Products
var originalInventory = productInventory.Inventory;
if (!productInventory.TryReduceInventory(quantity))
if (!productInventory.TryReduceInventory(quantity, increaseSold))
{
return false;
}
@ -97,13 +99,13 @@ namespace EasyAbp.EShop.Products.Products
await _productInventoryRepository.UpdateAsync(productInventory, true);
PublishInventoryChangedEventOnUowCompleted(productInventory.ProductId, productInventory.ProductSkuId,
originalInventory, productInventory.Inventory);
originalInventory, productInventory.Inventory, productInventory.Sold);
return true;
}
protected virtual void PublishInventoryChangedEventOnUowCompleted(Guid productId, Guid productSkuId,
int originalInventory, int newInventory)
int originalInventory, int newInventory, long sold)
{
_unitOfWorkManager.Current.OnCompleted(async () => await _distributedEventBus.PublishAsync(
new ProductInventoryChangedEto
@ -111,7 +113,8 @@ namespace EasyAbp.EShop.Products.Products
ProductId = productId,
ProductSkuId = productSkuId,
OriginalInventory = originalInventory,
NewInventory = newInventory
NewInventory = newInventory,
Sold = sold
}
));
}

11
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountManager.cs

@ -1,11 +0,0 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
namespace EasyAbp.EShop.Products.Products
{
public interface IProductDiscountManager : IDomainService
{
Task<decimal> GetDiscountedPriceAsync(Product product, ProductSku productSku, Guid storeId);
}
}

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

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

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

@ -23,10 +23,12 @@ namespace EasyAbp.EShop.Products.Products
Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, int quantity);
Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId);
Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId);
Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity);
Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool reduceSold);
Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity);
Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool increaseSold);
Task<decimal> GetDiscountedPriceAsync(Product product, ProductSku productSku, Guid storeId);
}
}

9
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/InventoryDataModel.cs

@ -0,0 +1,9 @@
namespace EasyAbp.EShop.Products.Products
{
public class InventoryDataModel
{
public int Inventory { get; set; }
public long Sold { get; set; }
}
}

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

@ -38,7 +38,7 @@ namespace EasyAbp.EShop.Products.Products
using var uow = _unitOfWorkManager.Begin(isTransactional: true);
var models = new List<ReduceInventoryModel>();
var models = new List<ConsumeInventoryModel>();
foreach (var orderLine in eventData.Entity.OrderLines)
{
@ -67,7 +67,7 @@ namespace EasyAbp.EShop.Products.Products
return;
}
models.Add(new ReduceInventoryModel
models.Add(new ConsumeInventoryModel
{
Product = product,
ProductSku = productSku,
@ -79,7 +79,7 @@ namespace EasyAbp.EShop.Products.Products
foreach (var model in models)
{
if (await _productManager.TryReduceInventoryAsync(model.Product, model.ProductSku, model.StoreId,
model.Quantity))
model.Quantity, true))
{
continue;
}

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

@ -37,7 +37,7 @@ namespace EasyAbp.EShop.Products.Products
using var uow = _unitOfWorkManager.Begin(isTransactional: true);
var models = new List<ReduceInventoryModel>();
var models = new List<ConsumeInventoryModel>();
foreach (var orderLine in eventData.Order.OrderLines)
{
@ -66,7 +66,7 @@ namespace EasyAbp.EShop.Products.Products
return;
}
models.Add(new ReduceInventoryModel
models.Add(new ConsumeInventoryModel
{
Product = product,
ProductSku = productSku,
@ -78,7 +78,7 @@ namespace EasyAbp.EShop.Products.Products
foreach (var model in models)
{
if (await _productManager.TryReduceInventoryAsync(model.Product, model.ProductSku, model.StoreId,
model.Quantity))
model.Quantity, true))
{
continue;
}

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

@ -23,6 +23,9 @@ namespace EasyAbp.EShop.Products.Products
[CanBeNull]
public virtual string MediaResources { get; protected set; }
[CanBeNull]
public virtual string SpecifiedInventoryProviderName { get; protected set; }
public virtual int DisplayOrder { get; protected set; }
public virtual bool IsPublished { get; protected set; }
@ -50,6 +53,7 @@ namespace EasyAbp.EShop.Products.Products
bool isStatic,
bool isHidden,
[CanBeNull] string mediaResources,
[CanBeNull] string specifiedInventoryProviderName,
int displayOrder
) : base(id)
{
@ -62,6 +66,7 @@ namespace EasyAbp.EShop.Products.Products
IsStatic = isStatic;
IsHidden = isHidden;
MediaResources = mediaResources;
SpecifiedInventoryProviderName = specifiedInventoryProviderName;
DisplayOrder = displayOrder;
ProductAttributes = new List<ProductAttribute>();

22
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductDiscountManager.cs

@ -1,22 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Domain.Services;
namespace EasyAbp.EShop.Products.Products
{
public class ProductDiscountManager : DomainService, IProductDiscountManager
{
public async Task<decimal> GetDiscountedPriceAsync(Product product, ProductSku productSku, Guid storeId)
{
var currentPrice = productSku.Price;
foreach (var provider in ServiceProvider.GetServices<IProductDiscountProvider>())
{
currentPrice = await provider.GetDiscountedPriceAsync(product, productSku, storeId, currentPrice);
}
return currentPrice;
}
}
}

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

@ -3,32 +3,30 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.ProductDetails;
using EasyAbp.EShop.Products.ProductStores;
using Volo.Abp.Domain.Entities;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Domain.Services;
namespace EasyAbp.EShop.Products.Products
{
public class ProductManager : DomainService, IProductManager
{
protected Dictionary<string, IProductInventoryProvider> InventoryProviders;
private readonly IProductRepository _productRepository;
private readonly IProductStoreRepository _productStoreRepository;
private readonly IProductCategoryRepository _productCategoryRepository;
private readonly IProductInventoryProvider _productInventoryProvider;
private readonly IAttributeOptionIdsSerializer _attributeOptionIdsSerializer;
public ProductManager(
IProductRepository productRepository,
IProductStoreRepository productStoreRepository,
IProductCategoryRepository productCategoryRepository,
IProductInventoryProvider productInventoryProvider,
IAttributeOptionIdsSerializer attributeOptionIdsSerializer)
{
_productRepository = productRepository;
_productStoreRepository = productStoreRepository;
_productCategoryRepository = productCategoryRepository;
_productInventoryProvider = productInventoryProvider;
_attributeOptionIdsSerializer = attributeOptionIdsSerializer;
}
@ -186,24 +184,54 @@ namespace EasyAbp.EShop.Products.Products
public virtual async Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
{
var inventory = await _productInventoryProvider.GetInventoryAsync(product, productSku, storeId);
var inventoryData = await GetInventoryProviderOrDefault(product, productSku)
.GetInventoryDataAsync(product, productSku, storeId);
return product.InventoryStrategy == InventoryStrategy.NoNeed || inventory - quantity >= 0;
return product.InventoryStrategy == InventoryStrategy.NoNeed || inventoryData.Inventory - quantity >= 0;
}
public virtual async Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId)
{
return await GetInventoryProviderOrDefault(product, productSku)
.GetInventoryDataAsync(product, productSku, storeId);
}
public virtual async Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId)
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool reduceSold)
{
return await _productInventoryProvider.GetInventoryAsync(product, productSku, storeId);
return await GetInventoryProviderOrDefault(product, productSku)
.TryIncreaseInventoryAsync(product, productSku, storeId, quantity, reduceSold);
}
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity, bool increaseSold)
{
return await _productInventoryProvider.TryIncreaseInventoryAsync(product, productSku, storeId, quantity);
return await GetInventoryProviderOrDefault(product, productSku)
.TryReduceInventoryAsync(product, productSku, storeId, quantity, increaseSold);
}
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
protected virtual IProductInventoryProvider GetInventoryProviderOrDefault(Product product, ProductSku productSku)
{
return await _productInventoryProvider.TryReduceInventoryAsync(product, productSku, storeId, quantity);
var providerName = !productSku.SpecifiedInventoryProviderName.IsNullOrWhiteSpace()
? productSku.SpecifiedInventoryProviderName
: !product.SpecifiedInventoryProviderName.IsNullOrWhiteSpace()
? product.SpecifiedInventoryProviderName
: "Default";
InventoryProviders ??= ServiceProvider.GetServices<IProductInventoryProvider>()
.ToDictionary(p => p.ProviderName, p => p);
return InventoryProviders.GetOrDefault(providerName) ?? InventoryProviders["Default"];
}
public virtual async Task<decimal> GetDiscountedPriceAsync(Product product, ProductSku productSku, Guid storeId)
{
var currentPrice = productSku.Price;
foreach (var provider in ServiceProvider.GetServices<IProductDiscountProvider>())
{
currentPrice = await provider.GetDiscountedPriceAsync(product, productSku, storeId, currentPrice);
}
return currentPrice;
}
}
}

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

@ -26,6 +26,9 @@ namespace EasyAbp.EShop.Products.Products
[CanBeNull]
public virtual string MediaResources { get; protected set; }
[CanBeNull]
public virtual string SpecifiedInventoryProviderName { get; protected set; }
public Guid? ProductDetailId { get; set; }
protected ProductSku() {}
@ -40,6 +43,7 @@ namespace EasyAbp.EShop.Products.Products
int orderMinQuantity,
int orderMaxQuantity,
[CanBeNull] string mediaResources,
[CanBeNull] string specifiedInventoryProviderName,
Guid? productDetailId) : base(id)
{
SerializedAttributeOptionIds = serializedAttributeOptionIds;
@ -50,6 +54,7 @@ namespace EasyAbp.EShop.Products.Products
OrderMinQuantity = orderMinQuantity;
OrderMaxQuantity = orderMaxQuantity;
MediaResources = mediaResources;
SpecifiedInventoryProviderName = specifiedInventoryProviderName;
ProductDetailId = productDetailId;
}

22
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/ProductInventories/ProductInventoryRepository.cs

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.EntityFrameworkCore;
using EasyAbp.EShop.Products.Products;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
@ -16,16 +17,27 @@ namespace EasyAbp.EShop.Products.ProductInventories
{
}
public async Task<int> GetInventoryAsync(Guid productSkuId, CancellationToken cancellationToken = default)
public async Task<InventoryDataModel> GetInventoryDataAsync(Guid productSkuId, CancellationToken cancellationToken = default)
{
return await GetQueryable().Where(x => x.ProductSkuId == productSkuId).Select(x => x.Inventory)
return await GetQueryable()
.Where(x => x.ProductSkuId == productSkuId)
.Select(x => new InventoryDataModel
{
Inventory = x.Inventory,
Sold = x.Sold
})
.FirstOrDefaultAsync(cancellationToken);
}
public async Task<Dictionary<Guid, int>> GetInventoryDictionaryAsync(List<Guid> productSkuIds, CancellationToken cancellationToken = default)
public async Task<Dictionary<Guid, InventoryDataModel>> GetInventoryDataDictionaryAsync(List<Guid> productSkuIds, CancellationToken cancellationToken = default)
{
return await GetQueryable().Where(x => productSkuIds.Contains(x.ProductSkuId))
.ToDictionaryAsync(x => x.ProductSkuId, x => x.Inventory, cancellationToken);
return await GetQueryable()
.Where(x => productSkuIds.Contains(x.ProductSkuId))
.ToDictionaryAsync(x => x.ProductSkuId, x => new InventoryDataModel
{
Inventory = x.Inventory,
Sold = x.Sold
}, cancellationToken);
}
}
}

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

@ -49,7 +49,7 @@
<th>@L["ProductCode"]</th>
<th>@L["ProductDisplayName"]</th>
<th>@L["ProductInventoryStrategy"]</th>
<th>@L["ProductMediaResources"]</th>
<th>@L["ProductSold"]</th>
<th>@L["ProductIsPublished"]</th>
</tr>
</thead>

6
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/ViewModels/CreateEditProductViewModel.cs

@ -48,11 +48,15 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewM
public InventoryStrategy InventoryStrategy { get; set; }
[Display(Name = "ProductDisplayOrder")]
public int DisplayOrder { get; set; } = 0;
public int DisplayOrder { get; set; }
[Display(Name = "ProductMediaResources")]
public string MediaResources { get; set; }
[Placeholder("KeepEmptyIfDoNotKnow")]
[Display(Name = "ProductSpecifiedInventoryProviderName")]
public string SpecifiedInventoryProviderName { get; set; }
[Display(Name = "ProductIsPublished")]
public bool IsPublished { get; set; }
}

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

@ -54,7 +54,7 @@ $(function () {
{ data: "code" },
{ data: "displayName" },
{ data: "inventoryStrategy" },
{ data: "mediaResources" },
{ data: "sold" },
{ data: "isPublished" },
]
}));

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

@ -55,6 +55,7 @@
<th>@L["ProductSkuContentDescription"]</th>
<th>@L["ProductSkuPrice"]</th>
<th>@L["ProductSkuInventory"]</th>
<th>@L["ProductSkuSold"]</th>
</tr>
</thead>
</abp-table>

5
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/EditProductSkuViewModel.cs

@ -2,6 +2,7 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels
{
@ -34,6 +35,10 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.Vi
[Display(Name = "ProductSkuMediaResources")]
public string MediaResources { get; set; }
[Placeholder("KeepEmptyIfDoNotKnow")]
[Display(Name = "ProductSkuSpecifiedInventoryProviderName")]
public string SpecifiedInventoryProviderName { get; set; }
[HiddenInput]
[Display(Name = "ProductSkuProductDetailId")]
public Guid? ProductDetailId { get; set; }

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

@ -63,6 +63,7 @@ $(function () {
{ data: "contentDescription" },
{ data: "price" },
{ data: "inventory" },
{ data: "sold" },
]
}));

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

@ -24,6 +24,7 @@ namespace EasyAbp.EShop.Products.Web
.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);
.ForMember(dest => dest.ProductAttributeNames,

3837
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706060054_AddedSpecifiedInventoryProviderName.Designer.cs

File diff suppressed because it is too large

31
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706060054_AddedSpecifiedInventoryProviderName.cs

@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace EShopSample.Migrations
{
public partial class AddedSpecifiedInventoryProviderName : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "SpecifiedInventoryProviderName",
table: "EShopProductsProductSkus",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "SpecifiedInventoryProviderName",
table: "EShopProductsProducts",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "SpecifiedInventoryProviderName",
table: "EShopProductsProductSkus");
migrationBuilder.DropColumn(
name: "SpecifiedInventoryProviderName",
table: "EShopProductsProducts");
}
}
}

3837
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706070250_ChangedSoldToLong.Designer.cs

File diff suppressed because it is too large

27
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706070250_ChangedSoldToLong.cs

@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace EShopSample.Migrations
{
public partial class ChangedSoldToLong : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<long>(
name: "Sold",
table: "EShopProductsProductInventories",
nullable: false,
oldClrType: typeof(int),
oldType: "int");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "Sold",
table: "EShopProductsProductInventories",
type: "int",
nullable: false,
oldClrType: typeof(long));
}
}
}

10
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/EShopSampleMigrationsDbContextModelSnapshot.cs

@ -916,8 +916,8 @@ namespace EShopSample.Migrations
b.Property<Guid>("ProductSkuId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Sold")
.HasColumnType("int");
b.Property<long>("Sold")
.HasColumnType("bigint");
b.HasKey("Id");
@ -1129,6 +1129,9 @@ namespace EShopSample.Migrations
b.Property<Guid>("ProductTypeId")
.HasColumnType("uniqueidentifier");
b.Property<string>("SpecifiedInventoryProviderName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("EShopProductsProducts");
@ -1310,6 +1313,9 @@ namespace EShopSample.Migrations
b.Property<string>("SerializedAttributeOptionIds")
.HasColumnType("nvarchar(max)");
b.Property<string>("SpecifiedInventoryProviderName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("ProductId");

Loading…
Cancel
Save