mirror of https://github.com/EasyAbp/EShop.git
58 changed files with 4733 additions and 121 deletions
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
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
@ -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; } |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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 |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
} |
|||
@ -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" } |
|||
); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku.ViewModels |
|||
{ |
|||
public enum InventoryChangeType |
|||
{ |
|||
IncreaseInventory, |
|||
DecreaseInventory, |
|||
} |
|||
} |
|||
@ -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
|
|||
} |
|||
} |
|||
} |
|||
@ -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
|
|||
} |
|||
} |
|||
} |
|||
@ -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
|
|||
}); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -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); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue