Browse Source

Merge pull request #113 from EasyAbp/product-view

Introduce ProductView aggregate root
pull/116/head
Super 5 years ago
committed by GitHub
parent
commit
f9b9dcb1ec
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/GetProductListInput.cs
  2. 40
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductViewDto.cs
  3. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/IProductAppService.cs
  4. 16
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/IProductViewAppService.cs
  5. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs
  6. 49
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
  7. 123
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductViewAppService.cs
  8. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
  9. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductInventories/ProductInventoryChangedEto.cs
  10. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp.EShop.Products.Domain.csproj
  11. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/EShopProductsDomainModule.cs
  12. 10
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/CacheItems/IProductViewCacheKeyProvider.cs
  13. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/CacheItems/ProductViewCacheItem.cs
  14. 14
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/CacheItems/ProductViewCacheKeyProvider.cs
  15. 21
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/DefaultProductInventoryProvider.cs
  16. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductViewRepository.cs
  17. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductViewSoldDataUpdater.cs
  18. 5
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/Product.cs
  19. 88
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductView.cs
  20. 35
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductViewSoldDataUpdater.cs
  21. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Settings/ProductsSettingDefinitionProvider.cs
  22. 7
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Settings/ProductsSettings.cs
  23. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/EShopProductsEntityFrameworkCoreModule.cs
  24. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/IProductsDbContext.cs
  25. 1
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs
  26. 17
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs
  27. 20
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/ProductViewEfCoreQuerableExtensions.cs
  28. 40
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/ProductViewRepository.cs
  29. 2
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/Products/ProductController.cs
  30. 35
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/Products/ProductViewController.cs
  31. 3
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/Product/index.js
  32. 3
      samples/EShopSample/aspnet-core/src/EShopSample.DbMigrator/appsettings.json
  33. 5073
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090325_AddedProductView.Designer.cs
  34. 72
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090325_AddedProductView.cs
  35. 5073
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090855_ConfiguredDecimalPropertiesInProductView.Designer.cs
  36. 49
      samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090855_ConfiguredDecimalPropertiesInProductView.cs
  37. 80
      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/Products/Dtos/GetProductListDto.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/GetProductListInput.cs

@ -5,7 +5,7 @@ using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Products.Products.Dtos
{
[Serializable]
public class GetProductListDto : PagedAndSortedResultRequestDto
public class GetProductListInput : PagedAndSortedResultRequestDto
{
[Required]
public Guid StoreId { get; set; }

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

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Products.Products.Dtos
{
[Serializable]
public class ProductViewDto : ExtensibleCreationAuditedEntityDto<Guid>
{
public Guid StoreId { get; set; }
public string ProductGroupName { get; set; }
public Guid ProductDetailId { get; set; }
public string UniqueName { get; set; }
public string DisplayName { get; set; }
public InventoryStrategy InventoryStrategy { get; set; }
public string MediaResources { get; set; }
public int DisplayOrder { get; set; }
public bool IsPublished { get; set; }
public bool IsStatic { get; set; }
public bool IsHidden { get; set; }
public decimal? MinimumPrice { get; set; }
public decimal? MaximumPrice { get; set; }
public long Sold { get; set; }
public string ProductGroupDisplayName { get; set; }
}
}

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

@ -10,7 +10,7 @@ namespace EasyAbp.EShop.Products.Products
ICrudAppService<
ProductDto,
Guid,
GetProductListDto,
GetProductListInput,
CreateUpdateProductDto,
CreateUpdateProductDto>
{

16
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/IProductViewAppService.cs

@ -0,0 +1,16 @@
using System;
using EasyAbp.EShop.Products.Products.Dtos;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace EasyAbp.EShop.Products.Products
{
public interface IProductViewAppService :
IReadOnlyAppService<
ProductViewDto,
Guid,
GetProductListInput>
{
}
}

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

@ -57,17 +57,18 @@ namespace EasyAbp.EShop.Products.ProductInventories
await _repository.InsertAsync(productInventory, true);
}
await ChangeInventoryAsync(productInventory, input.ChangedInventory);
await ChangeInventoryAsync(product, productInventory, input.ChangedInventory);
return ObjectMapper.Map<ProductInventory, ProductInventoryDto>(productInventory);
}
protected virtual async Task ChangeInventoryAsync(ProductInventory productInventory, int changedInventory)
protected virtual async Task ChangeInventoryAsync(Product product, ProductInventory productInventory,
int changedInventory)
{
if (changedInventory >= 0)
{
if (!await _productInventoryProvider.TryIncreaseInventoryAsync(productInventory, changedInventory,
false))
if (!await _productInventoryProvider.TryIncreaseInventoryAsync(product, productInventory,
changedInventory, false))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);
@ -75,8 +76,8 @@ namespace EasyAbp.EShop.Products.ProductInventories
}
else
{
if (!await _productInventoryProvider.TryReduceInventoryAsync(productInventory, -changedInventory, false)
)
if (!await _productInventoryProvider.TryReduceInventoryAsync(product, productInventory,
-changedInventory, false))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);

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

@ -6,14 +6,16 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Options;
using EasyAbp.EShop.Products.Products.CacheItems;
using EasyAbp.EShop.Stores.Stores;
using Microsoft.Extensions.Options;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Entities;
namespace EasyAbp.EShop.Products.Products
{
public class ProductAppService : MultiStoreCrudAppService<Product, ProductDto, Guid, GetProductListDto, CreateUpdateProductDto, CreateUpdateProductDto>, IProductAppService
public class ProductAppService : MultiStoreCrudAppService<Product, ProductDto, Guid, GetProductListInput, CreateUpdateProductDto, CreateUpdateProductDto>, IProductAppService
{
protected override string CreatePolicyName { get; set; } = ProductsPermissions.Products.Create;
protected override string DeletePolicyName { get; set; } = ProductsPermissions.Products.Delete;
@ -23,26 +25,32 @@ namespace EasyAbp.EShop.Products.Products
protected override string CrossStorePolicyName { get; set; } = ProductsPermissions.Products.CrossStore;
private readonly IProductManager _productManager;
private readonly IDistributedCache<ProductViewCacheItem> _cache;
private readonly EShopProductsOptions _options;
private readonly IProductInventoryProvider _productInventoryProvider;
private readonly IProductViewCacheKeyProvider _productViewCacheKeyProvider;
private readonly IAttributeOptionIdsSerializer _attributeOptionIdsSerializer;
private readonly IProductRepository _repository;
public ProductAppService(
IProductManager productManager,
IOptions<EShopProductsOptions> options,
IDistributedCache<ProductViewCacheItem> cache,
IProductInventoryProvider productInventoryProvider,
IProductViewCacheKeyProvider productViewCacheKeyProvider,
IAttributeOptionIdsSerializer attributeOptionIdsSerializer,
IProductRepository repository) : base(repository)
{
_productManager = productManager;
_cache = cache;
_options = options.Value;
_productInventoryProvider = productInventoryProvider;
_productViewCacheKeyProvider = productViewCacheKeyProvider;
_attributeOptionIdsSerializer = attributeOptionIdsSerializer;
_repository = repository;
}
protected override IQueryable<Product> CreateFilteredQuery(GetProductListDto input)
protected override IQueryable<Product> CreateFilteredQuery(GetProductListInput input)
{
var query = input.CategoryId.HasValue
? _repository.WithDetails(input.CategoryId.Value)
@ -76,10 +84,20 @@ namespace EasyAbp.EShop.Products.Products
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
UnitOfWorkManager.Current.OnCompleted(async () =>
{
await ClearProductViewCacheAsync(product.StoreId);
});
return dto;
}
protected virtual async Task ClearProductViewCacheAsync(Guid storeId)
{
await _cache.RemoveAsync(await _productViewCacheKeyProvider.GetCacheKeyAsync(storeId));
}
public override async Task<ProductDto> UpdateAsync(Guid id, CreateUpdateProductDto input)
{
var product = await GetEntityByIdAsync(id);
@ -104,6 +122,11 @@ namespace EasyAbp.EShop.Products.Products
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
UnitOfWorkManager.Current.OnCompleted(async () =>
{
await ClearProductViewCacheAsync(product.StoreId);
});
return dto;
}
@ -230,7 +253,7 @@ namespace EasyAbp.EShop.Products.Products
return dto;
}
public override async Task<PagedResultDto<ProductDto>> GetListAsync(GetProductListDto input)
public override async Task<PagedResultDto<ProductDto>> GetListAsync(GetProductListInput input)
{
await CheckGetListPolicyAsync();
@ -330,6 +353,11 @@ namespace EasyAbp.EShop.Products.Products
CheckProductIsNotStatic(product);
await _productManager.DeleteAsync(product);
UnitOfWorkManager.Current.OnCompleted(async () =>
{
await ClearProductViewCacheAsync(product.StoreId);
});
}
private static void CheckProductIsNotStatic(Product product)
@ -359,6 +387,11 @@ namespace EasyAbp.EShop.Products.Products
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
UnitOfWorkManager.Current.OnCompleted(async () =>
{
await ClearProductViewCacheAsync(product.StoreId);
});
return dto;
}
@ -381,6 +414,11 @@ namespace EasyAbp.EShop.Products.Products
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
UnitOfWorkManager.Current.OnCompleted(async () =>
{
await ClearProductViewCacheAsync(product.StoreId);
});
return dto;
}
@ -401,6 +439,11 @@ namespace EasyAbp.EShop.Products.Products
await LoadDtoExtraDataAsync(product, dto);
await LoadDtosProductGroupDisplayNameAsync(new[] {dto});
UnitOfWorkManager.Current.OnCompleted(async () =>
{
await ClearProductViewCacheAsync(product.StoreId);
});
return dto;
}

123
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductViewAppService.cs

@ -0,0 +1,123 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Products.CacheItems;
using EasyAbp.EShop.Products.Products.Dtos;
using EasyAbp.EShop.Products.Settings;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.Uow;
namespace EasyAbp.EShop.Products.Products
{
public class ProductViewAppService : ReadOnlyAppService<ProductView, ProductViewDto, Guid, GetProductListInput>,
IProductViewAppService
{
protected override string GetPolicyName { get; set; } = null;
protected override string GetListPolicyName { get; set; } = null;
private readonly IProductViewCacheKeyProvider _productViewCacheKeyProvider;
private readonly IDistributedCache<ProductViewCacheItem> _cache;
private readonly IProductAppService _productAppService;
private readonly IProductViewRepository _repository;
public ProductViewAppService(
IProductViewCacheKeyProvider productViewCacheKeyProvider,
IDistributedCache<ProductViewCacheItem> cache,
IProductAppService productAppService,
IProductViewRepository repository) : base(repository)
{
_productViewCacheKeyProvider = productViewCacheKeyProvider;
_cache = cache;
_productAppService = productAppService;
_repository = repository;
}
protected override IQueryable<ProductView> CreateFilteredQuery(GetProductListInput input)
{
var query = input.CategoryId.HasValue
? _repository.WithDetails(input.CategoryId.Value)
: _repository.WithDetails();
return query
.Where(x => x.StoreId == input.StoreId)
.WhereIf(!input.ShowHidden, x => !x.IsHidden);
}
public override async Task<PagedResultDto<ProductViewDto>> GetListAsync(GetProductListInput input)
{
await CheckGetListPolicyAsync();
if (await _cache.GetAsync(await GetCacheKeyAsync(input.StoreId), true) == null)
{
await BuildStoreProductViewsAsync(input.StoreId);
}
var query = CreateFilteredQuery(input);
var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
var productViews = await AsyncExecuter.ToListAsync(query);
var entityDtos = await MapToGetListOutputDtosAsync(productViews);
return new PagedResultDto<ProductViewDto>(
totalCount,
entityDtos
);
}
protected virtual async Task<string> GetCacheKeyAsync(Guid storeId)
{
return await _productViewCacheKeyProvider.GetCacheKeyAsync(storeId);
}
public override async Task<ProductViewDto> GetAsync(Guid id)
{
await CheckGetPolicyAsync();
var productView = await GetEntityByIdAsync(id);
if (await _cache.GetAsync(await GetCacheKeyAsync(productView.StoreId), true) != null)
{
return await base.GetAsync(id);
}
await BuildStoreProductViewsAsync(productView.StoreId);
productView = await GetEntityByIdAsync(id);
return await MapToGetOutputDtoAsync(productView);
}
protected virtual async Task BuildStoreProductViewsAsync(Guid storeId)
{
var resultDto = await _productAppService.GetListAsync(new GetProductListInput
{
StoreId = storeId
});
using var uow = UnitOfWorkManager.Begin(true, true);
await _repository.DeleteAsync(x => x.StoreId == storeId, true);
foreach (var product in resultDto.Items)
{
await _repository.InsertAsync(ObjectMapper.Map<ProductDto, ProductView>(product));
}
await uow.CompleteAsync();
await _cache.SetAsync(await GetCacheKeyAsync(storeId), new ProductViewCacheItem(),
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Convert.ToInt32(
await SettingProvider.GetOrNullAsync(ProductsSettings.ProductView.CacheDurationSeconds)))
});
}
}
}

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

@ -67,6 +67,8 @@ namespace EasyAbp.EShop.Products
CreateMap<ProductHistory, ProductHistoryDto>();
CreateMap<ProductDetailHistory, ProductDetailHistoryDto>();
CreateMap<ProductInventory, ProductInventoryDto>();
CreateMap<ProductView, ProductViewDto>();
CreateMap<ProductDto, ProductView>(MemberList.Destination);
}
}
}

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

@ -6,6 +6,8 @@ namespace EasyAbp.EShop.Products.ProductInventories
[Serializable]
public class ProductInventoryChangedEto
{
public Guid StoreId { get; set; }
public Guid ProductId { get; set; }
public Guid ProductSkuId { get; set; }

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

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

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

@ -5,6 +5,7 @@ using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Stores;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Modularity;
@ -12,6 +13,7 @@ namespace EasyAbp.EShop.Products
{
[DependsOn(
typeof(EShopProductsDomainSharedModule),
typeof(AbpCachingModule),
typeof(AbpTreesDomainModule)
)]
public class EShopProductsDomainModule : AbpModule

10
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/CacheItems/IProductViewCacheKeyProvider.cs

@ -0,0 +1,10 @@
using System;
using System.Threading.Tasks;
namespace EasyAbp.EShop.Products.Products.CacheItems
{
public interface IProductViewCacheKeyProvider
{
Task<string> GetCacheKeyAsync(Guid storeId);
}
}

7
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/CacheItems/ProductViewCacheItem.cs

@ -0,0 +1,7 @@
namespace EasyAbp.EShop.Products.Products.CacheItems
{
public class ProductViewCacheItem
{
}
}

14
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/CacheItems/ProductViewCacheKeyProvider.cs

@ -0,0 +1,14 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace EasyAbp.EShop.Products.Products.CacheItems
{
public class ProductViewCacheKeyProvider : IProductViewCacheKeyProvider, ITransientDependency
{
public virtual Task<string> GetCacheKeyAsync(Guid storeId)
{
return Task.FromResult(storeId.ToString());
}
}
}

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

@ -48,17 +48,17 @@ namespace EasyAbp.EShop.Products.Products
{
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);
return await TryIncreaseInventoryAsync(productInventory, quantity, decreaseSold);
return await TryIncreaseInventoryAsync(product, productInventory, quantity, decreaseSold);
}
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductSku productSku, int quantity, bool increaseSold)
{
var productInventory = await _productInventoryRepository.GetAsync(x => x.ProductSkuId == productSku.Id);
return await TryReduceInventoryAsync(productInventory, quantity, increaseSold);
return await TryReduceInventoryAsync(product, productInventory, quantity, increaseSold);
}
public virtual async Task<bool> TryIncreaseInventoryAsync(ProductInventory productInventory, int quantity, bool decreaseSold)
public virtual async Task<bool> TryIncreaseInventoryAsync(Product product, ProductInventory productInventory, int quantity, bool decreaseSold)
{
if (quantity < 0)
{
@ -75,16 +75,16 @@ namespace EasyAbp.EShop.Products.Products
using var uow = _unitOfWorkManager.Begin(isTransactional: true);
await _productInventoryRepository.UpdateAsync(productInventory, true);
PublishInventoryChangedEventOnUowCompleted(uow, productInventory.ProductId, productInventory.ProductSkuId,
originalInventory, productInventory.Inventory, productInventory.Sold);
PublishInventoryChangedEventOnUowCompleted(uow, product.StoreId, productInventory.ProductId,
productInventory.ProductSkuId, originalInventory, productInventory.Inventory, productInventory.Sold);
await uow.CompleteAsync();
return true;
}
public virtual async Task<bool> TryReduceInventoryAsync(ProductInventory productInventory, int quantity, bool increaseSold)
public virtual async Task<bool> TryReduceInventoryAsync(Product product, ProductInventory productInventory, int quantity, bool increaseSold)
{
if (quantity < 0)
{
@ -102,19 +102,20 @@ namespace EasyAbp.EShop.Products.Products
await _productInventoryRepository.UpdateAsync(productInventory, true);
PublishInventoryChangedEventOnUowCompleted(uow, productInventory.ProductId, productInventory.ProductSkuId,
originalInventory, productInventory.Inventory, productInventory.Sold);
PublishInventoryChangedEventOnUowCompleted(uow, product.StoreId, productInventory.ProductId,
productInventory.ProductSkuId, originalInventory, productInventory.Inventory, productInventory.Sold);
await uow.CompleteAsync();
return true;
}
protected virtual void PublishInventoryChangedEventOnUowCompleted(IUnitOfWork uow, Guid productId,
protected virtual void PublishInventoryChangedEventOnUowCompleted(IUnitOfWork uow, Guid storeId, Guid productId,
Guid productSkuId, int originalInventory, int newInventory, long sold)
{
uow.OnCompleted(async () => await _distributedEventBus.PublishAsync(new ProductInventoryChangedEto
{
StoreId = storeId,
ProductId = productId,
ProductSkuId = productSkuId,
OriginalInventory = originalInventory,

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

@ -0,0 +1,13 @@
using System;
using System.Linq;
using Volo.Abp.Domain.Repositories;
namespace EasyAbp.EShop.Products.Products
{
public interface IProductViewRepository : IRepository<ProductView, Guid>
{
IQueryable<ProductView> GetQueryable(Guid categoryId);
IQueryable<ProductView> WithDetails(Guid categoryId);
}
}

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

@ -0,0 +1,7 @@
namespace EasyAbp.EShop.Products.Products
{
public interface IProductViewSoldDataUpdater
{
}
}

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

@ -1,7 +1,6 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Domain.Entities.Auditing;
namespace EasyAbp.EShop.Products.Products
@ -47,7 +46,7 @@ namespace EasyAbp.EShop.Products.Products
Guid storeId,
[NotNull] string productGroupName,
Guid productDetailId,
[CanBeNull] string code,
[CanBeNull] string uniqueName,
[NotNull] string displayName,
InventoryStrategy inventoryStrategy,
bool isPublished,
@ -60,7 +59,7 @@ namespace EasyAbp.EShop.Products.Products
StoreId = storeId;
ProductGroupName = productGroupName;
ProductDetailId = productDetailId;
UniqueName = code?.Trim();
UniqueName = uniqueName?.Trim();
DisplayName = displayName;
InventoryStrategy = inventoryStrategy;
IsPublished = isPublished;

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

@ -0,0 +1,88 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace EasyAbp.EShop.Products.Products
{
public class ProductView : CreationAuditedAggregateRoot<Guid>, IProduct
{
#region Properties of IProduct
public virtual Guid StoreId { get; protected set; }
public virtual string ProductGroupName { get; protected set; }
public virtual Guid ProductDetailId { get; protected set; }
public virtual string UniqueName { get; protected set; }
public virtual string DisplayName { get; protected set; }
public virtual InventoryStrategy InventoryStrategy { get; protected set; }
public virtual string MediaResources { get; protected set; }
public virtual int DisplayOrder { get; protected set; }
public virtual bool IsPublished { get; protected set; }
public virtual bool IsStatic { get; protected set; }
public virtual bool IsHidden { get; protected set; }
#endregion
public virtual string ProductGroupDisplayName { get; protected set; }
public virtual decimal? MinimumPrice { get; protected set; }
public virtual decimal? MaximumPrice { get; protected set; }
public virtual long Sold { get; protected set; }
protected ProductView()
{
}
public ProductView(
Guid id,
Guid storeId,
string productGroupName,
Guid productDetailId,
string uniqueName,
string displayName,
InventoryStrategy inventoryStrategy,
bool isPublished,
bool isStatic,
bool isHidden,
string mediaResources,
int displayOrder,
string productGroupDisplayName,
decimal? minimumPrice,
decimal? maximumPrice,
long sold
) : base(id)
{
StoreId = storeId;
ProductGroupName = productGroupName;
ProductDetailId = productDetailId;
UniqueName = uniqueName?.Trim();
DisplayName = displayName;
InventoryStrategy = inventoryStrategy;
IsPublished = isPublished;
IsStatic = isStatic;
IsHidden = isHidden;
MediaResources = mediaResources;
DisplayOrder = displayOrder;
ProductGroupDisplayName = productGroupDisplayName;
MinimumPrice = minimumPrice;
MaximumPrice = maximumPrice;
Sold = sold;
}
public void SetSold(long sold)
{
Sold = sold;
}
}
}

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

@ -0,0 +1,35 @@
using System;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.Products.CacheItems;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
namespace EasyAbp.EShop.Products.Products
{
public class ProductViewSoldDataUpdater : IDistributedEventHandler<ProductInventoryChangedEto>,
IProductViewSoldDataUpdater, ITransientDependency
{
private readonly IProductViewCacheKeyProvider _productViewCacheKeyProvider;
private readonly IDistributedCache<ProductViewCacheItem> _cache;
public ProductViewSoldDataUpdater(
IProductViewCacheKeyProvider productViewCacheKeyProvider,
IDistributedCache<ProductViewCacheItem> cache)
{
_productViewCacheKeyProvider = productViewCacheKeyProvider;
_cache = cache;
}
public async Task HandleEventAsync(ProductInventoryChangedEto eventData)
{
await ClearProductViewCacheAsync(eventData.StoreId);
}
protected virtual async Task ClearProductViewCacheAsync(Guid storeId)
{
await _cache.RemoveAsync(await _productViewCacheKeyProvider.GetCacheKeyAsync(storeId));
}
}
}

2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Settings/ProductsSettingDefinitionProvider.cs

@ -9,6 +9,8 @@ namespace EasyAbp.EShop.Products.Settings
/* Define module settings here.
* Use names from ProductsSettings class.
*/
context.Add(new SettingDefinition(ProductsSettings.ProductView.CacheDurationSeconds, "60"));
}
}
}

7
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Settings/ProductsSettings.cs

@ -7,5 +7,12 @@
/* Add constants for setting names. Example:
* public const string MySettingName = GroupName + ".MySettingName";
*/
public class ProductView
{
private const string ProductViewGroupName = GroupName + ".GroupName";
public const string CacheDurationSeconds = ProductViewGroupName + ".CacheDuration";
}
}
}

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

@ -33,6 +33,7 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
options.AddRepository<ProductHistory, ProductHistoryRepository>();
options.AddRepository<ProductDetailHistory, ProductDetailHistoryRepository>();
options.AddRepository<ProductInventory, ProductInventoryRepository>();
options.AddRepository<ProductView, ProductViewRepository>();
});
}
}

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

@ -27,5 +27,6 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
DbSet<ProductHistory> ProductHistories { get; set; }
DbSet<ProductDetailHistory> ProductDetailHistories { get; set; }
DbSet<ProductInventory> ProductInventories { get; set; }
DbSet<ProductView> ProductViews { get; set; }
}
}

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

@ -27,6 +27,7 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
public DbSet<ProductHistory> ProductHistories { get; set; }
public DbSet<ProductDetailHistory> ProductDetailHistories { get; set; }
public DbSet<ProductInventory> ProductInventories { get; set; }
public DbSet<ProductView> ProductViews { get; set; }
public ProductsDbContext(DbContextOptions<ProductsDbContext> options)
: base(options)

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

@ -53,7 +53,7 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
b.ConfigureByConvention();
/* Configure more properties here */
b.HasIndex(x => x.UniqueName).IsUnique();
b.HasIndex(x => x.UniqueName);
});
builder.Entity<ProductDetail>(b =>
@ -92,6 +92,7 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
b.ConfigureByConvention();
/* Configure more properties here */
// Todo: soft delete support?
b.HasIndex(x => x.UniqueName).IsUnique();
});
@ -129,6 +130,20 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
b.HasIndex(x => x.ProductSkuId);
});
builder.Entity<ProductView>(b =>
{
b.ToTable(options.TablePrefix + "ProductViews", options.Schema);
b.ConfigureByConvention();
/* Configure more properties here */
b.HasIndex(x => x.UniqueName);
b.Property(x => x.MinimumPrice).HasColumnType("decimal(20,8)");
b.Property(x => x.MaximumPrice).HasColumnType("decimal(20,8)");
});
}
}
}

20
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/ProductViewEfCoreQuerableExtensions.cs

@ -0,0 +1,20 @@
using System.Linq;
using Microsoft.EntityFrameworkCore;
namespace EasyAbp.EShop.Products.Products
{
public static class ProductViewEfCoreQueryableExtensions
{
public static IQueryable<ProductView> IncludeDetails(this IQueryable<ProductView> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
// .Include(x => x.xxx) // TODO: AbpHelper generated
;
}
}
}

40
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/Products/ProductViewRepository.cs

@ -0,0 +1,40 @@
using System;
using System.Linq;
using EasyAbp.EShop.Products.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace EasyAbp.EShop.Products.Products
{
public class ProductViewRepository : EfCoreRepository<IProductsDbContext, ProductView, Guid>, IProductViewRepository
{
public ProductViewRepository(IDbContextProvider<IProductsDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public override IQueryable<ProductView> WithDetails()
{
return base.GetQueryable().IncludeDetails();
}
public IQueryable<ProductView> GetQueryable(Guid categoryId)
{
return JoinProductCategories(DbSet, categoryId);
}
public IQueryable<ProductView> WithDetails(Guid categoryId)
{
return JoinProductCategories(WithDetails(), categoryId);
}
protected virtual IQueryable<ProductView> JoinProductCategories(IQueryable<ProductView> queryable, Guid categoryId)
{
return queryable.Join(
DbContext.ProductCategories.Where(productCategory => productCategory.CategoryId == categoryId),
product => product.Id,
productCategory => productCategory.ProductId,
(product, productCategory) => product
);
}
}
}

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

@ -19,7 +19,7 @@ namespace EasyAbp.EShop.Products.Products
}
[HttpGet]
public Task<PagedResultDto<ProductDto>> GetListAsync(GetProductListDto input)
public Task<PagedResultDto<ProductDto>> GetListAsync(GetProductListInput input)
{
return _service.GetListAsync(input);
}

35
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/Products/ProductViewController.cs

@ -0,0 +1,35 @@
using System;
using EasyAbp.EShop.Products.Products.Dtos;
using Volo.Abp.Application.Dtos;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Products.Products
{
[RemoteService(Name = "EasyAbpEShopProducts")]
[Route("/api/e-shop/products/product/view")]
public class ProductViewController : ProductsController, IProductViewAppService
{
private readonly IProductViewAppService _service;
public ProductViewController(IProductViewAppService service)
{
_service = service;
}
[HttpGet]
public virtual Task<PagedResultDto<ProductViewDto>> GetListAsync(GetProductListInput input)
{
return _service.GetListAsync(input);
}
[HttpGet]
[Route("{id}")]
public virtual Task<ProductViewDto> GetAsync(Guid id)
{
return _service.GetAsync(id);
}
}
}

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

@ -3,6 +3,7 @@ $(function () {
var l = abp.localization.getResource('EasyAbpEShopProducts');
var service = easyAbp.eShop.products.products.product;
var viewService = easyAbp.eShop.products.products.productView;
var createModal = new abp.ModalManager(abp.appPath + 'EShop/Products/Products/Product/CreateModal');
var editModal = new abp.ModalManager(abp.appPath + 'EShop/Products/Products/Product/EditModal');
@ -13,7 +14,7 @@ $(function () {
searching: false,
autoWidth: false,
scrollCollapse: true,
ajax: abp.libs.datatables.createAjax(service.getList, function () {
ajax: abp.libs.datatables.createAjax(viewService.getList, function () {
return { storeId: storeId, categoryId: categoryId, showHidden: true }
}),
columnDefs: [

3
samples/EShopSample/aspnet-core/src/EShopSample.DbMigrator/appsettings.json

@ -1,6 +1,7 @@
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=EShopSample;Trusted_Connection=True;MultipleActiveResultSets=true"
"Default": "Server=60.208.32.153;Database=fenghui01test;User Id=fenghui01test;Password=WYSytJdMORYnhTYmvf;Trusted_Connection=True;Integrated Security=false"
},
"IdentityServer": {
"Clients": {

5073
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090325_AddedProductView.Designer.cs

File diff suppressed because it is too large

72
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090325_AddedProductView.cs

@ -0,0 +1,72 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace EShopSample.Migrations
{
public partial class AddedProductView : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_EasyAbpEShopProductsProducts_UniqueName",
table: "EasyAbpEShopProductsProducts");
migrationBuilder.CreateTable(
name: "EasyAbpEShopProductsProductViews",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
StoreId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ProductGroupName = table.Column<string>(type: "nvarchar(max)", nullable: true),
ProductDetailId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
UniqueName = table.Column<string>(type: "nvarchar(450)", nullable: true),
DisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
InventoryStrategy = table.Column<int>(type: "int", nullable: false),
MediaResources = table.Column<string>(type: "nvarchar(max)", nullable: true),
DisplayOrder = table.Column<int>(type: "int", nullable: false),
IsPublished = table.Column<bool>(type: "bit", nullable: false),
IsStatic = table.Column<bool>(type: "bit", nullable: false),
IsHidden = table.Column<bool>(type: "bit", nullable: false),
ProductGroupDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
MinimumPrice = table.Column<decimal>(type: "decimal(18,2)", nullable: true),
MaximumPrice = table.Column<decimal>(type: "decimal(18,2)", nullable: true),
Sold = table.Column<long>(type: "bigint", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_EasyAbpEShopProductsProductViews", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_EasyAbpEShopProductsProducts_UniqueName",
table: "EasyAbpEShopProductsProducts",
column: "UniqueName");
migrationBuilder.CreateIndex(
name: "IX_EasyAbpEShopProductsProductViews_UniqueName",
table: "EasyAbpEShopProductsProductViews",
column: "UniqueName");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "EasyAbpEShopProductsProductViews");
migrationBuilder.DropIndex(
name: "IX_EasyAbpEShopProductsProducts_UniqueName",
table: "EasyAbpEShopProductsProducts");
migrationBuilder.CreateIndex(
name: "IX_EasyAbpEShopProductsProducts_UniqueName",
table: "EasyAbpEShopProductsProducts",
column: "UniqueName",
unique: true,
filter: "[UniqueName] IS NOT NULL");
}
}
}

5073
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090855_ConfiguredDecimalPropertiesInProductView.Designer.cs

File diff suppressed because it is too large

49
samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore.DbMigrations/Migrations/20210118090855_ConfiguredDecimalPropertiesInProductView.cs

@ -0,0 +1,49 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace EShopSample.Migrations
{
public partial class ConfiguredDecimalPropertiesInProductView : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<decimal>(
name: "MinimumPrice",
table: "EasyAbpEShopProductsProductViews",
type: "decimal(20,8)",
nullable: true,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)",
oldNullable: true);
migrationBuilder.AlterColumn<decimal>(
name: "MaximumPrice",
table: "EasyAbpEShopProductsProductViews",
type: "decimal(20,8)",
nullable: true,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)",
oldNullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<decimal>(
name: "MinimumPrice",
table: "EasyAbpEShopProductsProductViews",
type: "decimal(18,2)",
nullable: true,
oldClrType: typeof(decimal),
oldType: "decimal(20,8)",
oldNullable: true);
migrationBuilder.AlterColumn<decimal>(
name: "MaximumPrice",
table: "EasyAbpEShopProductsProductViews",
type: "decimal(18,2)",
nullable: true,
oldClrType: typeof(decimal),
oldType: "decimal(20,8)",
oldNullable: true);
}
}
}

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

@ -1386,9 +1386,7 @@ namespace EShopSample.Migrations
b.HasKey("Id");
b.HasIndex("UniqueName")
.IsUnique()
.HasFilter("[UniqueName] IS NOT NULL");
b.HasIndex("UniqueName");
b.ToTable("EasyAbpEShopProductsProducts");
});
@ -1588,6 +1586,82 @@ namespace EShopSample.Migrations
b.ToTable("EasyAbpEShopProductsProductSkus");
});
modelBuilder.Entity("EasyAbp.EShop.Products.Products.ProductView", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<int>("DisplayOrder")
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<int>("InventoryStrategy")
.HasColumnType("int");
b.Property<bool>("IsHidden")
.HasColumnType("bit");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<bool>("IsStatic")
.HasColumnType("bit");
b.Property<decimal?>("MaximumPrice")
.HasColumnType("decimal(20,8)");
b.Property<string>("MediaResources")
.HasColumnType("nvarchar(max)");
b.Property<decimal?>("MinimumPrice")
.HasColumnType("decimal(20,8)");
b.Property<Guid>("ProductDetailId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ProductGroupDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("ProductGroupName")
.HasColumnType("nvarchar(max)");
b.Property<long>("Sold")
.HasColumnType("bigint");
b.Property<Guid>("StoreId")
.HasColumnType("uniqueidentifier");
b.Property<string>("UniqueName")
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UniqueName");
b.ToTable("EasyAbpEShopProductsProductViews");
});
modelBuilder.Entity("EasyAbp.EShop.Stores.StoreOwners.StoreOwner", b =>
{
b.Property<Guid>("Id")

Loading…
Cancel
Save