Browse Source

Close #75: Implement sold data of products.

pull/87/head
gdlcf88 6 years ago
parent
commit
f8fee2e859
  1. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/ProductInventoryDto.cs
  2. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductDto.cs
  3. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs
  4. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs
  5. 26
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
  6. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
  7. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/cs.json
  8. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
  9. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pl.json
  10. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pt-BR.json
  11. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/sl.json
  12. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/tr.json
  13. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/vi.json
  14. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
  15. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
  16. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductInventories/ProductInventoryChangedEto.cs
  17. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/IProductInventoryRepository.cs
  18. 24
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/ProductInventory.cs
  19. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ConsumeInventoryModel.cs
  20. 35
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductInventoryProvider.cs
  21. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductInventoryProvider.cs
  22. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductManager.cs
  23. 9
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/InventoryDataModel.cs
  24. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderCreatedEventHandler.cs
  25. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/OrderPaidEventHandler.cs
  26. 20
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs
  27. 22
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/ProductInventories/ProductInventoryRepository.cs
  28. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/Index.cshtml
  29. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/index.js
  30. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/Index.cshtml
  31. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/index.js
  32. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/ProductsWebAutoMapperProfile.cs
  33. 3837
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706070250_ChangedSoldToLong.Designer.cs
  34. 27
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200706070250_ChangedSoldToLong.cs
  35. 4
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/EShopSampleMigrationsDbContextModelSnapshot.cs

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; }
}
}

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

@ -30,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; }

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

@ -23,7 +23,7 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public int Inventory { get; set; }
public int Sold { get; set; }
public long Sold { get; set; }
public int OrderMinQuantity { 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);

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

@ -199,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;
}
@ -218,7 +218,7 @@ namespace EasyAbp.EShop.Products.Products
var dto = MapToGetOutputDto(product);
await LoadRealInventoriesAsync(product, dto, storeId);
await LoadDtoInventoryDataAsync(product, dto, storeId);
return dto;
}
@ -256,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);
}
@ -265,19 +265,25 @@ 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)
{
@ -369,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>();

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

@ -27,6 +27,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -28,6 +28,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -27,6 +27,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -27,6 +27,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -28,6 +28,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -28,6 +28,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -27,6 +27,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -28,6 +28,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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

@ -28,6 +28,7 @@
"ProductSkuOriginalPrice": "ProductSkuOriginalPrice",
"ProductSkuPrice": "ProductSkuPrice",
"ProductSkuInventory": "ProductSkuInventory",
"ProductSkuSold": "ProductSkuSold",
"ProductSkuOrderMinQuantity": "ProductSkuOrderMinQuantity",
"ProductSkuOrderMaxQuantity": "ProductSkuOrderMaxQuantity",
"ProductSkuMediaResources": "ProductSkuMediaResources",

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; }

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

@ -28,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)
{
@ -69,7 +69,7 @@ namespace EasyAbp.EShop.Products.Products
var originalInventory = productInventory.Inventory;
if (!productInventory.TryIncreaseInventory(quantity))
if (!productInventory.TryIncreaseInventory(quantity, decreaseSold))
{
return false;
}
@ -77,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)
{
@ -91,7 +91,7 @@ namespace EasyAbp.EShop.Products.Products
var originalInventory = productInventory.Inventory;
if (!productInventory.TryReduceInventory(quantity))
if (!productInventory.TryReduceInventory(quantity, increaseSold))
{
return false;
}
@ -99,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
@ -113,7 +113,8 @@ namespace EasyAbp.EShop.Products.Products
ProductId = productId,
ProductSkuId = productSkuId,
OriginalInventory = originalInventory,
NewInventory = newInventory
NewInventory = newInventory,
Sold = sold
}
));
}

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

@ -8,12 +8,12 @@ namespace EasyAbp.EShop.Products.Products
{
string ProviderName { get; }
Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId);
Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId);
Task<Dictionary<Guid, int>> GetInventoryDictionaryAsync(Product product, 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);
}
}

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

@ -23,11 +23,11 @@ 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;
}

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

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -184,28 +184,28 @@ namespace EasyAbp.EShop.Products.Products
public virtual async Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
{
var inventory = await GetInventoryProviderOrDefault(product, productSku)
.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<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId)
public virtual async Task<InventoryDataModel> GetInventoryDataAsync(Product product, ProductSku productSku, Guid storeId)
{
return await GetInventoryProviderOrDefault(product, productSku)
.GetInventoryAsync(product, productSku, storeId);
.GetInventoryDataAsync(product, productSku, storeId);
}
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 reduceSold)
{
return await GetInventoryProviderOrDefault(product, productSku)
.TryIncreaseInventoryAsync(product, productSku, storeId, quantity);
.TryIncreaseInventoryAsync(product, productSku, storeId, quantity, reduceSold);
}
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)
{
return await GetInventoryProviderOrDefault(product, productSku)
.TryReduceInventoryAsync(product, productSku, storeId, quantity);
.TryReduceInventoryAsync(product, productSku, storeId, quantity, increaseSold);
}
protected virtual IProductInventoryProvider GetInventoryProviderOrDefault(Product product, ProductSku productSku)

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>

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>

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/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));
}
}
}

4
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");

Loading…
Cancel
Save