Browse Source

Close #74: Introduce ProductInventory aggregate root

pull/87/head
gdlcf88 6 years ago
parent
commit
28a03e7a38
  1. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissionDefinitionProvider.cs
  2. 12
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissions.cs
  3. 17
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/ProductInventoryDto.cs
  4. 18
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/UpdateProductInventoryDto.cs
  5. 15
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/IProductInventoryAppService.cs
  6. 3
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/CreateUpdateProductSkuDto.cs
  7. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs
  8. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Categories/CategoryAppService.cs
  9. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductCategories/ProductCategoryAppService.cs
  10. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductDetailHistories/ProductDetailHistoryAppService.cs
  11. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductDetails/ProductDetailAppService.cs
  12. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductHistories/ProductHistoryAppService.cs
  13. 100
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs
  14. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductTypes/ProductTypeAppService.cs
  15. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
  16. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
  17. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/cs.json
  18. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
  19. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pl.json
  20. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/pt-BR.json
  21. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/sl.json
  22. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/tr.json
  23. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/vi.json
  24. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
  25. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
  26. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductInventories/ProductInventoryChangedEto.cs
  27. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductSku.cs
  28. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/ProductSkuEto.cs
  29. 15
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/IProductInventoryRepository.cs
  30. 58
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/ProductInventories/ProductInventory.cs
  31. 105
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductInventoryProvider.cs
  32. 4
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/InventoryChangeFailedException.cs
  33. 33
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductSku.cs
  34. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/EShopProductsEntityFrameworkCoreModule.cs
  35. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/IProductsDbContext.cs
  36. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs
  37. 11
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs
  38. 31
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/ProductInventories/ProductInventoryRepository.cs
  39. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/EasyAbp.EShop.Products.Web.csproj
  40. 3
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Menus/ProductsMenuContributor.cs
  41. 21
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ChangeInventoryModal.cshtml
  42. 60
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ChangeInventoryModal.cshtml.cs
  43. 23
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/CreateModal.cshtml.cs
  44. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/EditModal.cshtml.cs
  45. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/Index.cshtml
  46. 15
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/ChangeProductInventoryViewModel.cs
  47. 24
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/CreateProductSkuViewModel.cs
  48. 6
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/EditProductSkuViewModel.cs
  49. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/InventoryChangeType.cs
  50. 14
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/index.js
  51. 12
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/ProductsWebAutoMapperProfile.cs
  52. 26
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/ProductInventories/ProductInventoryAppServiceTests.cs
  53. 23
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Domain.Tests/ProductInventories/ProductInventoryDomainTests.cs
  54. 31
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductInventories/ProductInventoryRepositoryTests.cs
  55. 4
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs
  56. 3831
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200705195503_RedesignedInventory.Designer.cs
  57. 68
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200705195503_RedesignedInventory.cs
  58. 71
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/EShopSampleMigrationsDbContextModelSnapshot.cs

8
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Authorization/ProductsPermissionDefinitionProvider.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissionDefinitionProvider.cs

@ -3,7 +3,7 @@ using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
namespace EasyAbp.EShop.Products.Authorization
namespace EasyAbp.EShop.Products.Permissions
{
public class ProductsPermissionDefinitionProvider : PermissionDefinitionProvider
{
@ -27,6 +27,10 @@ namespace EasyAbp.EShop.Products.Authorization
product.AddChild(ProductsPermissions.Products.Create, L("Permission:Create"));
product.AddChild(ProductsPermissions.Products.Update, L("Permission:Update"));
product.AddChild(ProductsPermissions.Products.Delete, L("Permission:Delete"));
var productInventoryPermission = moduleGroup.AddPermission(ProductsPermissions.ProductInventory.Default, L("Permission:ProductInventory"));
productInventoryPermission.AddChild(ProductsPermissions.ProductInventory.CrossStore, L("Permission:CrossStore"));
productInventoryPermission.AddChild(ProductsPermissions.ProductInventory.Update, L("Permission:Update"));
}
private static LocalizableString L(string name)
@ -34,4 +38,4 @@ namespace EasyAbp.EShop.Products.Authorization
return LocalizableString.Create<ProductsResource>(name);
}
}
}
}

12
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Authorization/ProductsPermissions.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Permissions/ProductsPermissions.cs

@ -1,6 +1,6 @@
using Volo.Abp.Reflection;
namespace EasyAbp.EShop.Products.Authorization
namespace EasyAbp.EShop.Products.Permissions
{
public class ProductsPermissions
{
@ -36,5 +36,13 @@ namespace EasyAbp.EShop.Products.Authorization
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(ProductsPermissions));
}
public class ProductInventory
{
public const string Default = GroupName + ".ProductInventory";
public const string CrossStore = Default + ".CrossStore";
public const string Update = Default + ".Update";
}
}
}
}

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

@ -0,0 +1,17 @@
using System;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Products.ProductInventories.Dtos
{
[Serializable]
public class ProductInventoryDto : FullAuditedEntityDto<Guid>
{
public Guid ProductId { get; set; }
public Guid ProductSkuId { get; set; }
public int Inventory { get; set; }
public int Sold { get; set; }
}
}

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

@ -0,0 +1,18 @@
using System;
namespace EasyAbp.EShop.Products.ProductInventories.Dtos
{
[Serializable]
public class UpdateProductInventoryDto
{
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>
public int ChangedInventory { get; set; }
}
}

15
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/IProductInventoryAppService.cs

@ -0,0 +1,15 @@
using System;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace EasyAbp.EShop.Products.ProductInventories
{
public interface IProductInventoryAppService : IApplicationService
{
Task<ProductInventoryDto> GetAsync(Guid productId, Guid productSkuId);
Task<ProductInventoryDto> UpdateAsync(UpdateProductInventoryDto input);
}
}

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

@ -20,9 +20,6 @@ namespace EasyAbp.EShop.Products.Products.Dtos
[DisplayName("ProductSkuPrice")]
public decimal Price { get; set; }
[DisplayName("ProductSkuInventory")]
public int Inventory { get; set; }
[DefaultValue(1)]
[DisplayName("ProductSkuOrderMinQuantity")]
public int OrderMinQuantity { get; set; }

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

@ -24,16 +24,8 @@ namespace EasyAbp.EShop.Products.Products.Dtos
/// </summary>
public decimal DiscountedPrice { get; set; }
/// <summary>
/// Inventory property in the ProductSku entity.
/// </summary>
public int Inventory { get; set; }
/// <summary>
/// Inventory provider's inventory quantity (same as Inventory property if there is no provider).
/// </summary>
public int RealInventory { get; set; }
public int Sold { get; set; }
public int OrderMinQuantity { get; set; }

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Categories/CategoryAppService.cs

@ -1,8 +1,8 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Categories.Dtos;
using EasyAbp.EShop.Products.Permissions;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductCategories/ProductCategoryAppService.cs

@ -1,7 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductCategories.Dtos;
using Volo.Abp;
using Volo.Abp.Application.Dtos;

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductDetailHistories/ProductDetailHistoryAppService.cs

@ -1,7 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductDetailHistories.Dtos;
using Volo.Abp;
using Volo.Abp.Application.Services;

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

@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.ProductStores;

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductHistories/ProductHistoryAppService.cs

@ -1,7 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductHistories.Dtos;
using Volo.Abp;
using Volo.Abp.Application.Services;

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

@ -0,0 +1,100 @@
using System;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.ProductStores;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Abp.Validation;
namespace EasyAbp.EShop.Products.ProductInventories
{
public class ProductInventoryAppService : ApplicationService, IProductInventoryAppService
{
private readonly IProductInventoryRepository _repository;
private readonly IProductStoreRepository _productStoreRepository;
private readonly DefaultProductInventoryProvider _productInventoryProvider;
public ProductInventoryAppService(
IProductInventoryRepository repository,
IProductStoreRepository productStoreRepository,
DefaultProductInventoryProvider productInventoryProvider)
{
_repository = repository;
_productStoreRepository = productStoreRepository;
_productInventoryProvider = productInventoryProvider;
}
[Authorize(ProductsPermissions.ProductInventory.Default)]
public virtual async Task<ProductInventoryDto> GetAsync(Guid productId, Guid productSkuId)
{
var productInventory = await _repository.FindAsync(x => x.ProductSkuId == productSkuId);
if (productInventory == null)
{
productInventory = new ProductInventory(GuidGenerator.Create(), productId, productSkuId, 0, 0);
await _repository.InsertAsync(productInventory, true);
}
return ObjectMapper.Map<ProductInventory, ProductInventoryDto>(productInventory);
}
[Authorize(ProductsPermissions.ProductInventory.Update)]
public virtual async Task<ProductInventoryDto> UpdateAsync(UpdateProductInventoryDto input)
{
if (!await AuthorizationService.IsGrantedAsync(ProductsPermissions.ProductInventory.CrossStore))
{
if (!input.StoreId.HasValue)
{
throw new AbpValidationException("StoreId should not be null.");
}
// Todo: Check if current user is an admin of the store.
await _productStoreRepository.GetAsync(input.ProductId, input.StoreId.Value);
}
var productInventory = await _repository.FindAsync(x => x.ProductSkuId == input.ProductSkuId);
if (productInventory == null)
{
productInventory =
new ProductInventory(GuidGenerator.Create(), input.ProductId, input.ProductSkuId, 0, 0);
await ChangeInventoryAsync(productInventory, input.ChangedInventory);
await _repository.InsertAsync(productInventory, true);
}
else
{
await ChangeInventoryAsync(productInventory, input.ChangedInventory);
await _repository.UpdateAsync(productInventory, true);
}
return ObjectMapper.Map<ProductInventory, ProductInventoryDto>(productInventory);
}
protected virtual async Task ChangeInventoryAsync(ProductInventory productInventory, int changedInventory)
{
if (changedInventory >= 0)
{
if (!await _productInventoryProvider.TryIncreaseInventoryAsync(productInventory, changedInventory))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);
}
}
else
{
if (!await _productInventoryProvider.TryReduceInventoryAsync(productInventory, -changedInventory))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);
}
}
}
}
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductTypes/ProductTypeAppService.cs

@ -1,5 +1,5 @@
using System;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductTypes.Dtos;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;

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

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.Products.Dtos;
using EasyAbp.EShop.Products.ProductStores;
using Microsoft.AspNetCore.Authorization;
@ -274,7 +274,7 @@ namespace EasyAbp.EShop.Products.Products
foreach (var productSkuDto in productDto.ProductSkus)
{
productSkuDto.RealInventory = inventoryDict[productSkuDto.Id];
productSkuDto.Inventory = inventoryDict[productSkuDto.Id];
}
return productDto;

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

@ -15,6 +15,8 @@ using EasyAbp.EShop.Products.ProductDetailHistories.Dtos;
using EasyAbp.EShop.Products.ProductHistories;
using EasyAbp.EShop.Products.ProductHistories.Dtos;
using Volo.Abp.AutoMapper;
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using Volo.Abp.DependencyInjection;
namespace EasyAbp.EShop.Products
@ -36,7 +38,8 @@ namespace EasyAbp.EShop.Products
.ForSourceMember(entity => entity.SerializedAttributeOptionIds, opt => opt.DoNotValidate())
.Ignore(dto => dto.AttributeOptionIds)
.Ignore(dto => dto.DiscountedPrice)
.Ignore(dto => dto.RealInventory)
.Ignore(dto => dto.Inventory)
.Ignore(dto => dto.Sold)
.AfterMap(async (src, dest) => dest.AttributeOptionIds =
(await attributeOptionIdsSerializer.DeserializeAsync(src.SerializedAttributeOptionIds)).ToList());
CreateMap<CreateUpdateProductDto, Product>(MemberList.Source)
@ -63,6 +66,7 @@ namespace EasyAbp.EShop.Products
CreateMap<ProductCategory, ProductCategoryDto>();
CreateMap<ProductHistory, ProductHistoryDto>();
CreateMap<ProductDetailHistory, ProductDetailHistoryDto>();
CreateMap<ProductInventory, ProductInventoryDto>();
}
}
}

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

@ -74,6 +74,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -75,6 +75,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -74,6 +74,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -74,6 +74,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -75,6 +75,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -75,6 +75,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -74,6 +74,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -75,6 +75,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -75,6 +75,17 @@
"ProductCategoryDisplayOrder": "ProductCategoryDisplayOrder",
"CreateProductCategory": "CreateProductCategory",
"EditProductCategory": "EditProductCategory",
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?"
"ProductCategoryDeletionConfirmationMessage": "Are you sure to delete the productcategory {0}?",
"Permission:ProductInventory": "ProductInventory",
"Permission:Create": "Create",
"Permission:Update": "Update",
"Permission:Delete": "Delete",
"ProductInventory": "ProductInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"IncreaseInventory": "Increase",
"DecreaseInventory": "Decrease",
"ProductInventoryInventory": "ProductInventoryInventory",
"ProductInventoryChangeType": "ProductInventoryChangeType",
"ChangeProductInventory": "ChangeProductInventory"
}
}

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

@ -3,12 +3,8 @@ using Volo.Abp.MultiTenancy;
namespace EasyAbp.EShop.Products.ProductInventories
{
public class ProductInventoryChangedEto : IMultiTenant
public class ProductInventoryChangedEto
{
public Guid Id { get; set; }
public Guid? TenantId { get; set; }
public Guid ProductId { get; set; }
public Guid ProductSkuId { get; set; }

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

@ -14,10 +14,6 @@ namespace EasyAbp.EShop.Products.Products
decimal Price { get; }
int Inventory { get; }
int Sold { get; }
int OrderMinQuantity { get; }
int OrderMaxQuantity { get; }

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

@ -16,10 +16,6 @@ namespace EasyAbp.EShop.Products.Products
public decimal Price { get; set; }
public int Inventory { get; set; }
public int Sold { get; set; }
public int OrderMinQuantity { get; set; }
public int OrderMaxQuantity { get; set; }

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

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
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<Dictionary<Guid, int>> GetInventoryDictionaryAsync(List<Guid> productSkuIds, CancellationToken cancellationToken = default);
}
}

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

@ -0,0 +1,58 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace EasyAbp.EShop.Products.ProductInventories
{
public class ProductInventory : FullAuditedAggregateRoot<Guid>
{
public virtual Guid ProductId { get; protected set; }
public virtual Guid ProductSkuId { get; protected set; }
public virtual int Inventory { get; protected set; }
// Todo: should be implemented
public virtual int Sold { get; protected set; }
protected ProductInventory()
{
}
public ProductInventory(
Guid id,
Guid productId,
Guid productSkuId,
int inventory,
int sold) : base(id)
{
ProductId = productId;
ProductSkuId = productSkuId;
Inventory = inventory;
Sold = sold;
}
internal bool TryIncreaseInventory(int quantity)
{
if (quantity < 0)
{
return false;
}
Inventory = checked(Inventory + quantity);
return true;
}
internal bool TryReduceInventory(int quantity)
{
if (quantity > Inventory || quantity < 0)
{
return false;
}
Inventory -= quantity;
return true;
}
}
}

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

@ -1,38 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductInventories;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Uow;
namespace EasyAbp.EShop.Products.Products
{
[Dependency(TryRegister = true)]
public class DefaultProductInventoryProvider : IProductInventoryProvider, ITransientDependency
{
public virtual Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId)
// Todo: should use IProductInventoryStore.
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IDistributedEventBus _distributedEventBus;
private readonly IProductInventoryRepository _productInventoryRepository;
public DefaultProductInventoryProvider(
IUnitOfWorkManager unitOfWorkManager,
IDistributedEventBus distributedEventBus,
IProductInventoryRepository productInventoryRepository)
{
_unitOfWorkManager = unitOfWorkManager;
_distributedEventBus = distributedEventBus;
_productInventoryRepository = productInventoryRepository;
}
public virtual async Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId)
{
return await _productInventoryRepository.GetInventoryAsync(productSku.Id);
}
public virtual async Task<Dictionary<Guid, int>> GetInventoryDictionaryAsync(Product product, Guid storeId)
{
var dict = await _productInventoryRepository.GetInventoryDictionaryAsync(product.ProductSkus
.Select(sku => sku.Id).ToList());
foreach (var sku in product.ProductSkus)
{
dict.GetOrAdd(sku.Id, () => 0);
}
return dict;
}
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
{
return Task.FromResult(productSku.Inventory);
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);
return await TryIncreaseInventoryAsync(productInventory, quantity);
}
public virtual Task<Dictionary<Guid, int>> GetInventoryDictionaryAsync(Product product, Guid storeId)
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
{
var dict = new Dictionary<Guid, int>();
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);
foreach (var productSku in product.ProductSkus)
return await TryReduceInventoryAsync(productInventory, quantity);
}
public virtual async Task<bool> TryIncreaseInventoryAsync(ProductInventory productInventory, int quantity)
{
if (quantity < 0)
{
dict[productSku.Id] = productSku.Inventory;
return false;
}
var originalInventory = productInventory.Inventory;
if (!productInventory.TryIncreaseInventory(quantity))
{
return false;
}
return Task.FromResult(dict);
await _productInventoryRepository.UpdateAsync(productInventory, true);
PublishInventoryChangedEventOnUowCompleted(productInventory.ProductId, productInventory.ProductSkuId,
originalInventory, productInventory.Inventory);
return true;
}
public virtual Task<bool> TryIncreaseInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
public virtual async Task<bool> TryReduceInventoryAsync(ProductInventory productInventory, int quantity)
{
return Task.FromResult(productSku.TryIncreaseInventory(quantity));
if (quantity < 0)
{
return false;
}
var originalInventory = productInventory.Inventory;
if (!productInventory.TryReduceInventory(quantity))
{
return false;
}
await _productInventoryRepository.UpdateAsync(productInventory, true);
PublishInventoryChangedEventOnUowCompleted(productInventory.ProductId, productInventory.ProductSkuId,
originalInventory, productInventory.Inventory);
return true;
}
public virtual Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, Guid storeId, int quantity)
protected virtual void PublishInventoryChangedEventOnUowCompleted(Guid productId, Guid productSkuId,
int originalInventory, int newInventory)
{
return Task.FromResult(productSku.TryReduceInventory(quantity));
_unitOfWorkManager.Current.OnCompleted(async () => await _distributedEventBus.PublishAsync(
new ProductInventoryChangedEto
{
ProductId = productId,
ProductSkuId = productSkuId,
OriginalInventory = originalInventory,
NewInventory = newInventory
}
));
}
}
}

4
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductSkuInventoryChangeFailedException.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/InventoryChangeFailedException.cs

@ -3,9 +3,9 @@ using Volo.Abp;
namespace EasyAbp.EShop.Products.Products
{
public class ProductSkuInventoryChangeFailedException : BusinessException
public class InventoryChangeFailedException : BusinessException
{
public ProductSkuInventoryChangeFailedException(Guid productId, Guid productSkuId, int originalInventory,
public InventoryChangeFailedException(Guid productId, Guid productSkuId, int originalInventory,
int changedInventory) : base(
message:
$"Inventory of product {productId} (SKU: {productSkuId}) cannot be changed by {changedInventory} from {originalInventory}")

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

@ -19,11 +19,6 @@ namespace EasyAbp.EShop.Products.Products
public virtual decimal Price { get; protected set; }
public virtual int Inventory { get; protected set; }
// Todo: should be implemented
public virtual int Sold { get; protected set; }
public virtual int OrderMinQuantity { get; protected set; }
public virtual int OrderMaxQuantity { get; protected set; }
@ -42,8 +37,6 @@ namespace EasyAbp.EShop.Products.Products
[NotNull] string currency,
decimal? originalPrice,
decimal price,
int inventory,
int sold,
int orderMinQuantity,
int orderMaxQuantity,
[CanBeNull] string mediaResources,
@ -54,38 +47,12 @@ namespace EasyAbp.EShop.Products.Products
Currency = currency;
OriginalPrice = originalPrice;
Price = price;
Inventory = inventory;
Sold = sold;
OrderMinQuantity = orderMinQuantity;
OrderMaxQuantity = orderMaxQuantity;
MediaResources = mediaResources;
ProductDetailId = productDetailId;
}
public bool TryIncreaseInventory(int quantity)
{
if (quantity <= 0)
{
return false;
}
Inventory = checked(Inventory + quantity);
return true;
}
public bool TryReduceInventory(int quantity)
{
if (quantity > Inventory || quantity <= 0)
{
return false;
}
Inventory -= quantity;
return true;
}
public void TrimCode()
{
Code = Code?.Trim();

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

@ -1,3 +1,4 @@
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.Abp.Trees.EntityFrameworkCore;
using EasyAbp.EShop.Products.ProductDetailHistories;
using EasyAbp.EShop.Products.ProductHistories;
@ -35,6 +36,7 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
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

@ -9,6 +9,7 @@ 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;
namespace EasyAbp.EShop.Products.EntityFrameworkCore
{
@ -29,5 +30,6 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
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

@ -9,6 +9,7 @@ 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;
namespace EasyAbp.EShop.Products.EntityFrameworkCore
{
@ -29,6 +30,7 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
public DbSet<ProductStore> ProductStores { get; set; }
public DbSet<ProductHistory> ProductHistories { get; set; }
public DbSet<ProductDetailHistory> ProductDetailHistories { get; set; }
public DbSet<ProductInventory> ProductInventories { get; set; }
public ProductsDbContext(DbContextOptions<ProductsDbContext> options)
: base(options)

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

@ -1,3 +1,4 @@
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.ProductDetailHistories;
using EasyAbp.EShop.Products.ProductHistories;
using EasyAbp.EShop.Products.ProductStores;
@ -130,6 +131,16 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
b.HasIndex(x => x.ProductDetailId);
b.HasIndex(x => x.ModificationTime);
});
builder.Entity<ProductInventory>(b =>
{
b.ToTable(options.TablePrefix + "ProductInventories", options.Schema);
b.ConfigureByConvention();
/* Configure more properties here */
b.HasIndex(x => x.ProductSkuId);
});
}
}
}

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

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace EasyAbp.EShop.Products.ProductInventories
{
public class ProductInventoryRepository : EfCoreRepository<ProductsDbContext, ProductInventory, Guid>, IProductInventoryRepository
{
public ProductInventoryRepository(IDbContextProvider<ProductsDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<int> GetInventoryAsync(Guid productSkuId, CancellationToken cancellationToken = default)
{
return await GetQueryable().Where(x => x.ProductSkuId == productSkuId).Select(x => x.Inventory)
.FirstOrDefaultAsync(cancellationToken);
}
public async Task<Dictionary<Guid, int>> GetInventoryDictionaryAsync(List<Guid> productSkuIds, CancellationToken cancellationToken = default)
{
return await GetQueryable().Where(x => productSkuIds.Contains(x.ProductSkuId))
.ToDictionaryAsync(x => x.ProductSkuId, x => x.Inventory, cancellationToken);
}
}
}

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

@ -27,6 +27,10 @@
<Content Remove="Pages\**\*.css" />
<Content Remove="Pages\**\*.js" />
<Content Remove="wwwroot\**\*.*" />
<Content Update="Pages\EShop\Products\Products\ProductSku\ChangeInventoryModal.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
@ -35,6 +39,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Pages\EShop\Products\ProductInventories" />
<Folder Include="wwwroot\" />
</ItemGroup>

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

@ -1,6 +1,7 @@
using System.Collections.Generic;
using EasyAbp.EShop.Products.Localization;
using EasyAbp.EShop.Products.Permissions;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Authorization;
using EasyAbp.EShop.Products.Localization;
using EasyAbp.EShop.Stores.Stores;
using Microsoft.Extensions.DependencyInjection;

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

@ -0,0 +1,21 @@
@page
@using EasyAbp.EShop.Products.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@inject IHtmlLocalizer<ProductsResource> L
@model EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ChangeInventoryModal
@{
Layout = null;
}
<abp-dynamic-form abp-model="ViewModel" data-ajaxForm="true" asp-page="ChangeInventoryModal">
<abp-modal>
<abp-modal-header title="@L["ChangeProductInventory"].Value"></abp-modal-header>
<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>
</abp-modal>
</abp-dynamic-form>

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

@ -0,0 +1,60 @@
using System;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
{
public class ChangeInventoryModal : ProductsPageModel
{
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductId { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductSkuId { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid StoreId { get; set; }
[BindProperty]
public ChangeProductInventoryViewModel ViewModel { get; set; }
private readonly IProductInventoryAppService _service;
public ChangeInventoryModal(IProductInventoryAppService service)
{
_service = service;
}
public virtual async Task OnGetAsync()
{
var dto = await _service.GetAsync(ProductId, ProductSkuId);
ViewModel = new ChangeProductInventoryViewModel
{
ChangedInventory = 0,
ProductInventoryChangeType = InventoryChangeType.IncreaseInventory
};
}
public virtual async Task<IActionResult> OnPostAsync()
{
await _service.UpdateAsync(new UpdateProductInventoryDto
{
ProductId = ProductId,
ProductSkuId = ProductSkuId,
StoreId = StoreId,
ChangedInventory = ViewModel.ProductInventoryChangeType == InventoryChangeType.IncreaseInventory
? ViewModel.ChangedInventory
: -ViewModel.ChangedInventory
});
return NoContent();
}
}
}

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

@ -2,12 +2,13 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos;
using EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Volo.Abp.Json;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
{
@ -22,21 +23,21 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public Guid ProductId { get; set; }
[BindProperty]
public CreateEditProductSkuViewModel ProductSku { get; set; }
public CreateProductSkuViewModel ProductSku { get; set; } = new CreateProductSkuViewModel();
[BindProperty]
public Dictionary<string, Guid> SelectedAttributeOptionIdDict { get; set; }
public Dictionary<string, ICollection<SelectListItem>> Attributes { get; set; }
private readonly IJsonSerializer _jsonSerializer;
private readonly IProductInventoryAppService _productInventoryAppService;
private readonly IProductAppService _productAppService;
public CreateModalModel(
IJsonSerializer jsonSerializer,
IProductInventoryAppService productInventoryAppService,
IProductAppService productAppService)
{
_jsonSerializer = jsonSerializer;
_productInventoryAppService = productInventoryAppService;
_productAppService = productAppService;
}
@ -56,11 +57,19 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public virtual async Task<IActionResult> OnPostAsync()
{
var createDto = ObjectMapper.Map<CreateEditProductSkuViewModel, CreateProductSkuDto>(ProductSku);
var createDto = ObjectMapper.Map<CreateProductSkuViewModel, CreateProductSkuDto>(ProductSku);
createDto.AttributeOptionIds = SelectedAttributeOptionIdDict.Values.ToList();
await _productAppService.CreateSkuAsync(ProductId, StoreId, createDto);
var skuDto = await _productAppService.CreateSkuAsync(ProductId, StoreId, createDto);
await _productInventoryAppService.UpdateAsync(new UpdateProductInventoryDto
{
ProductId = ProductId,
ProductSkuId = skuDto.Id,
StoreId = StoreId,
ChangedInventory = ProductSku.Inventory
});
return NoContent();
}

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

@ -25,7 +25,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public Guid ProductSkuId { get; set; }
[BindProperty]
public CreateEditProductSkuViewModel ProductSku { get; set; }
public EditProductSkuViewModel ProductSku { get; set; }
private readonly IProductAppService _productAppService;
@ -39,14 +39,14 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
var product = await _productAppService.GetAsync(ProductId, StoreId);
ProductSku =
ObjectMapper.Map<ProductSkuDto, CreateEditProductSkuViewModel>(
ObjectMapper.Map<ProductSkuDto, EditProductSkuViewModel>(
product.ProductSkus.Single(x => x.Id == ProductSkuId));
}
public virtual async Task<IActionResult> OnPostAsync()
{
await _productAppService.UpdateSkuAsync(ProductId, ProductSkuId, StoreId,
ObjectMapper.Map<CreateEditProductSkuViewModel, UpdateProductSkuDto>(ProductSku));
ObjectMapper.Map<EditProductSkuViewModel, UpdateProductSkuDto>(ProductSku));
return NoContent();
}

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

@ -1,12 +1,15 @@
@page
@using EasyAbp.EShop.Products.Localization
@using EasyAbp.EShop.Products.Permissions
@using EasyAbp.EShop.Products.Web.Menus
@using EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@model IndexModel
@inject IPageLayout PageLayout
@inject IHtmlLocalizer<ProductsResource> L
@inject IAuthorizationService Authorization
@{
PageLayout.Content.Title = L["ProductSku"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:Product"].Value);
@ -33,10 +36,13 @@
<abp-card-title>@L["ProductSku"] - @Model.ProductDisplayName</abp-card-title>
</abp-column>
<abp-column size-md="_6" class="text-right">
@if (await Authorization.IsGrantedAsync(ProductsPermissions.Products.Create))
{
<abp-button id="NewProductSkuButton"
text="@L["CreateProductSku"].Value"
icon="plus"
button-type="Primary" />
}
</abp-column>
</abp-row>
</abp-card-header>

15
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/ChangeProductInventoryViewModel.cs

@ -0,0 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels
{
public class ChangeProductInventoryViewModel
{
[Display(Name = "ProductInventoryInventory")]
public int ChangedInventory { get; set; }
[Display(Name = "ProductInventoryChangeType")]
public InventoryChangeType ProductInventoryChangeType { get; set; }
}
}

24
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/CreateProductSkuViewModel.cs

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels
{
public class CreateProductSkuViewModel : EditProductSkuViewModel, IValidatableObject
{
[Required]
[Display(Name = "ProductSkuInventory")]
public int Inventory { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Inventory < 0)
{
yield return new ValidationResult(
"Inventory should greater than or equal to 0.",
new[] { "Inventory" }
);
}
}
}
}

6
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/CreateEditProductSkuViewModel.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/EditProductSkuViewModel.cs

@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Mvc;
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels
{
public class CreateEditProductSkuViewModel
public class EditProductSkuViewModel
{
[Display(Name = "ProductSkuCode")]
public string Code { get; set; }
@ -21,10 +21,6 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.Vi
[Display(Name = "ProductSkuOriginalPrice")]
public decimal? OriginalPrice { get; set; }
[Required]
[Display(Name = "ProductSkuInventory")]
public int Inventory { get; set; }
[Required]
[DefaultValue(1)]
[Display(Name = "ProductSkuOrderMinQuantity")]

8
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ViewModels/InventoryChangeType.cs

@ -0,0 +1,8 @@
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels
{
public enum InventoryChangeType
{
IncreaseInventory,
DecreaseInventory,
}
}

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

@ -5,6 +5,7 @@ $(function () {
var service = easyAbp.eShop.products.products.product;
var createModal = new abp.ModalManager(abp.appPath + 'EShop/Products/Products/ProductSku/CreateModal');
var editModal = new abp.ModalManager(abp.appPath + 'EShop/Products/Products/ProductSku/EditModal');
var changeInventoryModal = new abp.ModalManager(abp.appPath + 'EShop/Products/Products/ProductSku/ChangeInventoryModal');
var dataTable = $('#ProductSkuTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
@ -29,12 +30,21 @@ $(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 });
}
},
{
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 });
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('EasyAbp.EShop.Products.Product.Delete'),
confirmMessage: function (data) {
return l('ProductDeletionConfirmationMessage', data.record.id);
},
@ -64,6 +74,10 @@ $(function () {
dataTable.ajax.reload();
});
changeInventoryModal.onResult(function () {
dataTable.ajax.reload();
});
$('#NewProductSkuButton').click(function (e) {
e.preventDefault();
createModal.open({ storeId: storeId, productId: productId });

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

@ -8,6 +8,7 @@ using AutoMapper;
using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.Product.ViewModels;
using EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using Volo.Abp.AutoMapper;
namespace EasyAbp.EShop.Products.Web
@ -52,11 +53,14 @@ namespace EasyAbp.EShop.Products.Web
CreateMap<CreateEditProductDetailViewModel, CreateUpdateProductDetailDto>();
CreateMap<ProductAttributeDto, CreateEditProductAttributeViewModel>();
CreateMap<CreateEditProductAttributeViewModel, CreateUpdateProductAttributeDto>();
CreateMap<CreateEditProductSkuViewModel, CreateProductSkuDto>()
CreateMap<CreateProductSkuViewModel, CreateProductSkuDto>()
.ForSourceMember(model => model.Inventory, opt => opt.DoNotValidate())
.Ignore(dto => dto.AttributeOptionIds);
CreateMap<CreateEditProductSkuViewModel, UpdateProductSkuDto>();
CreateMap<ProductSkuDto, CreateEditProductSkuViewModel>()
.ForSourceMember(dto => dto.AttributeOptionIds, opt => opt.DoNotValidate());
CreateMap<EditProductSkuViewModel, UpdateProductSkuDto>();
CreateMap<ProductSkuDto, EditProductSkuViewModel>()
.ForSourceMember(dto => dto.AttributeOptionIds, opt => opt.DoNotValidate())
.ForSourceMember(dto => dto.Inventory, opt => opt.DoNotValidate())
.ForSourceMember(dto => dto.Sold, opt => opt.DoNotValidate());
CreateMap<ProductAttributeOptionDto, CreateEditProductAttributeOptionViewModel>();
CreateMap<CreateEditProductAttributeOptionViewModel, CreateUpdateProductAttributeOptionDto>();
CreateMap<CategoryDto, CreateUpdateCategoryDto>();

26
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/ProductInventories/ProductInventoryAppServiceTests.cs

@ -0,0 +1,26 @@
using Shouldly;
using System.Threading.Tasks;
using Xunit;
namespace EasyAbp.EShop.Products.ProductInventories
{
public class ProductInventoryAppServiceTests : ProductsApplicationTestBase
{
private readonly IProductInventoryAppService _productInventoryAppService;
public ProductInventoryAppServiceTests()
{
_productInventoryAppService = GetRequiredService<IProductInventoryAppService>();
}
[Fact]
public async Task Test1()
{
// Arrange
// Act
// Assert
}
}
}

23
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Domain.Tests/ProductInventories/ProductInventoryDomainTests.cs

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

31
modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductInventories/ProductInventoryRepositoryTests.cs

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

4
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs

@ -146,7 +146,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
return;
}
if (productDto.InventoryStrategy != InventoryStrategy.NoNeed && quantity > productSkuDto.RealInventory)
if (productDto.InventoryStrategy != InventoryStrategy.NoNeed && quantity > productSkuDto.Inventory)
{
item.SetIsInvalid(true);
}
@ -160,7 +160,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
UnitPrice = productSkuDto.DiscountedPrice,
TotalPrice = productSkuDto.DiscountedPrice * item.Quantity,
TotalDiscount = (productSkuDto.Price - productSkuDto.DiscountedPrice) * item.Quantity,
Inventory = productSkuDto.RealInventory
Inventory = productSkuDto.Inventory
});
if (!productDto.IsPublished)

3831
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200705195503_RedesignedInventory.Designer.cs

File diff suppressed because it is too large

68
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20200705195503_RedesignedInventory.cs

@ -0,0 +1,68 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace EShopSample.Migrations
{
public partial class RedesignedInventory : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Inventory",
table: "EShopProductsProductSkus");
migrationBuilder.DropColumn(
name: "Sold",
table: "EShopProductsProductSkus");
migrationBuilder.CreateTable(
name: "EShopProductsProductInventories",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
ExtraProperties = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(nullable: false),
CreatorId = table.Column<Guid>(nullable: true),
LastModificationTime = table.Column<DateTime>(nullable: true),
LastModifierId = table.Column<Guid>(nullable: true),
IsDeleted = table.Column<bool>(nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(nullable: true),
DeletionTime = table.Column<DateTime>(nullable: true),
ProductId = table.Column<Guid>(nullable: false),
ProductSkuId = table.Column<Guid>(nullable: false),
Inventory = table.Column<int>(nullable: false),
Sold = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EShopProductsProductInventories", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_EShopProductsProductInventories_ProductSkuId",
table: "EShopProductsProductInventories",
column: "ProductSkuId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "EShopProductsProductInventories");
migrationBuilder.AddColumn<int>(
name: "Inventory",
table: "EShopProductsProductSkus",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "Sold",
table: "EShopProductsProductSkus",
type: "int",
nullable: false,
defaultValue: 0);
}
}
}

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

@ -861,6 +861,71 @@ namespace EShopSample.Migrations
b.ToTable("EShopProductsProductHistories");
});
modelBuilder.Entity("EasyAbp.EShop.Products.ProductInventories.ProductInventory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnName("ConcurrencyStamp")
.HasColumnType("nvarchar(40)")
.HasMaxLength(40);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime2");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime")
.HasColumnType("datetime2");
b.Property<string>("ExtraProperties")
.HasColumnName("ExtraProperties")
.HasColumnType("nvarchar(max)");
b.Property<int>("Inventory")
.HasColumnType("int");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasColumnType("bit")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime")
.HasColumnType("datetime2");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("ProductId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("ProductSkuId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Sold")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ProductSkuId");
b.ToTable("EShopProductsProductInventories");
});
modelBuilder.Entity("EasyAbp.EShop.Products.ProductStores.ProductStore", b =>
{
b.Property<Guid>("Id")
@ -1207,9 +1272,6 @@ namespace EShopSample.Migrations
.HasColumnName("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("Inventory")
.HasColumnType("int");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
@ -1248,9 +1310,6 @@ namespace EShopSample.Migrations
b.Property<string>("SerializedAttributeOptionIds")
.HasColumnType("nvarchar(max)");
b.Property<int>("Sold")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ProductId");

Loading…
Cancel
Save