Browse Source

Merge pull request #162 from EasyAbp/remove-product-inventory-appservice

Use IProductAppService to change inventories
pull/165/head
Super 4 years ago
committed by GitHub
parent
commit
79862f5ec7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/ProductInventoryDto.cs
  2. 18
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/Dtos/UpdateProductInventoryDto.cs
  3. 15
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/ProductInventories/IProductInventoryAppService.cs
  4. 13
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ChangeProductInventoryDto.cs
  5. 14
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ChangeProductInventoryResultDto.cs
  6. 11
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/IProductAppService.cs
  7. 104
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductInventories/ProductInventoryAppService.cs
  8. 23
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
  9. 3
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
  10. 33
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/ProductInventories/ProductInventoryController.cs
  11. 8
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/Products/ProductController.cs
  12. 21
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/ChangeInventoryModal.cshtml.cs
  13. 22
      modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Web/Pages/EShop/Products/Products/ProductSku/CreateModal.cshtml.cs
  14. 26
      modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/ProductInventories/ProductInventoryAppServiceTests.cs

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

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

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

@ -1,18 +0,0 @@
using System;
using Volo.Abp.ObjectExtending;
namespace EasyAbp.EShop.Products.ProductInventories.Dtos
{
[Serializable]
public class UpdateProductInventoryDto : ExtensibleObject
{
public Guid ProductId { get; set; }
public Guid ProductSkuId { 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

@ -1,15 +0,0 @@
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);
}
}

13
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ChangeProductInventoryDto.cs

@ -0,0 +1,13 @@
using System;
using Volo.Abp.ObjectExtending;
namespace EasyAbp.EShop.Products.Products.Dtos;
[Serializable]
public class ChangeProductInventoryDto : ExtensibleObject
{
/// <summary>
/// Reduce inventory if the value is less than 0
/// </summary>
public int ChangedInventory { get; set; }
}

14
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ChangeProductInventoryResultDto.cs

@ -0,0 +1,14 @@
using System;
using Volo.Abp.ObjectExtending;
namespace EasyAbp.EShop.Products.Products.Dtos;
[Serializable]
public class ChangeProductInventoryResultDto : ExtensibleObject
{
public bool Changed { get; set; }
public int ChangedInventory { get; set; }
public int CurrentInventory { get; set; }
}

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

@ -7,9 +7,9 @@ using Volo.Abp.Application.Services;
namespace EasyAbp.EShop.Products.Products
{
public interface IProductAppService :
ICrudAppService<
ProductDto,
Guid,
ICrudAppService<
ProductDto,
Guid,
GetProductListInput,
CreateUpdateProductDto,
CreateUpdateProductDto>
@ -19,9 +19,12 @@ namespace EasyAbp.EShop.Products.Products
Task<ProductDto> UpdateSkuAsync(Guid productId, Guid productSkuId, UpdateProductSkuDto input);
Task<ProductDto> DeleteSkuAsync(Guid productId, Guid productSkuId);
Task<ProductDto> GetByUniqueNameAsync(Guid storeId, string uniqueName);
Task<ListResultDto<ProductGroupDto>> GetProductGroupListAsync();
Task<ChangeProductInventoryResultDto> ChangeInventoryAsync(Guid id, Guid productSkuId,
ChangeProductInventoryDto input);
}
}

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

@ -1,104 +0,0 @@
using EasyAbp.EShop.Products.Permissions;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Stores.Authorization;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
namespace EasyAbp.EShop.Products.ProductInventories
{
public class ProductInventoryAppService : ApplicationService, IProductInventoryAppService
{
private readonly IProductRepository _productRepository;
private readonly IProductInventoryRepository _repository;
private readonly DefaultProductInventoryProvider _defaultProductInventoryProvider;
public ProductInventoryAppService(
IProductRepository productRepository,
IProductInventoryRepository repository,
DefaultProductInventoryProvider defaultProductInventoryProvider)
{
_productRepository = productRepository;
_repository = repository;
_defaultProductInventoryProvider = defaultProductInventoryProvider;
}
[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)
{
var product = await _productRepository.GetAsync(productId);
if (!product.ProductSkus.Exists(x => x.Id == productSkuId))
{
throw new EntityNotFoundException(typeof(ProductSku), productSkuId);
}
productInventory = new ProductInventory(GuidGenerator.Create(), CurrentTenant.Id, productId,
productSkuId, 0, 0);
await _repository.InsertAsync(productInventory, true);
}
return ObjectMapper.Map<ProductInventory, ProductInventoryDto>(productInventory);
}
public virtual async Task<ProductInventoryDto> UpdateAsync(UpdateProductInventoryDto input)
{
var product = await _productRepository.GetAsync(input.ProductId);
if (!product.ProductSkus.Exists(x => x.Id == input.ProductSkuId))
{
throw new EntityNotFoundException(typeof(ProductSku), input.ProductSkuId);
}
await AuthorizationService.CheckMultiStorePolicyAsync(product.StoreId,
ProductsPermissions.ProductInventory.Update, ProductsPermissions.ProductInventory.CrossStore);
var productInventory = await _repository.FindAsync(x => x.ProductSkuId == input.ProductSkuId);
if (productInventory == null)
{
productInventory =
new ProductInventory(GuidGenerator.Create(), CurrentTenant.Id, input.ProductId, input.ProductSkuId,
0, 0);
await _repository.InsertAsync(productInventory, true);
}
await ChangeInventoryAsync(product, productInventory, input.ChangedInventory);
return ObjectMapper.Map<ProductInventory, ProductInventoryDto>(productInventory);
}
protected virtual async Task ChangeInventoryAsync(Product product, ProductInventory productInventory,
int changedInventory)
{
var model = new InventoryQueryModel(product.TenantId, product.StoreId, product.Id,
productInventory.ProductSkuId);
if (changedInventory >= 0)
{
if (!await _defaultProductInventoryProvider.TryIncreaseInventoryAsync(model, changedInventory, false))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);
}
}
else
{
if (!await _defaultProductInventoryProvider.TryReduceInventoryAsync(model, -changedInventory, false))
{
throw new InventoryChangeFailedException(productInventory.ProductId, productInventory.ProductSkuId,
productInventory.Inventory, changedInventory);
}
}
}
}
}

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

@ -442,6 +442,29 @@ namespace EasyAbp.EShop.Products.Products
).ToList()));
}
public virtual async Task<ChangeProductInventoryResultDto> ChangeInventoryAsync(Guid id, Guid productSkuId,
ChangeProductInventoryDto input)
{
var product = await GetEntityByIdAsync(id);
var sku = product.ProductSkus.Single(x => x.Id == productSkuId);
var changed = input.ChangedInventory switch
{
> 0 => await _productManager.TryIncreaseInventoryAsync(product, sku, input.ChangedInventory, false),
< 0 => await _productManager.TryReduceInventoryAsync(product, sku, -1 * input.ChangedInventory, false),
_ => false
};
var model = await _productManager.GetInventoryDataAsync(product, sku);
return new ChangeProductInventoryResultDto
{
Changed = changed,
ChangedInventory = input.ChangedInventory,
CurrentInventory = model.Inventory
};
}
protected override ProductDto MapToGetOutputDto(Product entity)
{
var productDto = base.MapToGetOutputDto(entity);

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

@ -9,8 +9,6 @@ using EasyAbp.EShop.Products.ProductDetails;
using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.ProductHistories;
using EasyAbp.EShop.Products.ProductHistories.Dtos;
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos;
using System.Linq;
@ -65,7 +63,6 @@ namespace EasyAbp.EShop.Products
CreateMap<ProductCategory, ProductCategoryDto>();
CreateMap<ProductHistory, ProductHistoryDto>();
CreateMap<ProductDetailHistory, ProductDetailHistoryDto>();
CreateMap<ProductInventory, ProductInventoryDto>();
CreateMap<ProductView, ProductViewDto>();
CreateMap<Product, ProductView>(MemberList.Destination);
}

33
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.HttpApi/EasyAbp/EShop/Products/ProductInventories/ProductInventoryController.cs

@ -1,33 +0,0 @@
using System;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductInventories.Dtos;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Products.ProductInventories
{
[RemoteService(Name = EShopProductsRemoteServiceConsts.RemoteServiceName)]
[Route("/api/e-shop/products/product-inventory")]
public class ProductInventoryController : ProductsController, IProductInventoryAppService
{
private readonly IProductInventoryAppService _service;
public ProductInventoryController(IProductInventoryAppService service)
{
_service = service;
}
[HttpGet]
public Task<ProductInventoryDto> GetAsync(Guid productId, Guid productSkuId)
{
return _service.GetAsync(productId, productSkuId);
}
[HttpPut]
public Task<ProductInventoryDto> UpdateAsync(UpdateProductInventoryDto input)
{
return _service.UpdateAsync(input);
}
}
}

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

@ -93,5 +93,13 @@ namespace EasyAbp.EShop.Products.Products
{
return _service.GetProductGroupListAsync();
}
[HttpPost]
[Route("{id}/sku/{productSkuId}/change-inventory")]
public Task<ChangeProductInventoryResultDto> ChangeInventoryAsync(Guid id, Guid productSkuId,
ChangeProductInventoryDto input)
{
return _service.ChangeInventoryAsync(id, productSkuId, input);
}
}
}

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

@ -1,7 +1,7 @@
using System;
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;
@ -12,7 +12,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductId { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductSkuId { get; set; }
@ -20,17 +20,18 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
[BindProperty]
public ChangeProductInventoryViewModel ViewModel { get; set; }
private readonly IProductInventoryAppService _service;
private readonly IProductAppService _service;
public ChangeInventoryModal(IProductInventoryAppService service)
public ChangeInventoryModal(IProductAppService service)
{
_service = service;
}
public virtual async Task OnGetAsync()
{
var dto = await _service.GetAsync(ProductId, ProductSkuId);
var product = await _service.GetAsync(ProductId);
product.GetSkuById(ProductSkuId); // ensure the specified sku exists.
ViewModel = new ChangeProductInventoryViewModel
{
ChangedInventory = 0,
@ -40,15 +41,13 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
public virtual async Task<IActionResult> OnPostAsync()
{
await _service.UpdateAsync(new UpdateProductInventoryDto
await _service.ChangeInventoryAsync(ProductId, ProductSkuId, new ChangeProductInventoryDto
{
ProductId = ProductId,
ProductSkuId = ProductSkuId,
ChangedInventory = ViewModel.ProductInventoryChangeType == InventoryChangeType.IncreaseInventory
? ViewModel.ChangedInventory
: -ViewModel.ChangedInventory
});
return NoContent();
}
}

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

@ -4,8 +4,6 @@ using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.ProductDetails;
using EasyAbp.EShop.Products.ProductDetails.Dtos;
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;
@ -19,25 +17,22 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid ProductId { get; set; }
[BindProperty]
public CreateProductSkuViewModel ProductSku { get; set; } = new CreateProductSkuViewModel();
[BindProperty]
public Dictionary<string, Guid> SelectedAttributeOptionIdDict { get; set; }
public Dictionary<string, List<SelectListItem>> Attributes { get; set; }
private readonly IProductInventoryAppService _productInventoryAppService;
private readonly IProductDetailAppService _productDetailAppService;
private readonly IProductAppService _productAppService;
public CreateModalModel(
IProductInventoryAppService productInventoryAppService,
IProductDetailAppService productDetailAppService,
IProductAppService productAppService)
{
_productInventoryAppService = productInventoryAppService;
_productDetailAppService = productDetailAppService;
_productAppService = productAppService;
}
@ -47,7 +42,7 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
var product = await _productAppService.GetAsync(ProductId);
Attributes = new Dictionary<string, List<SelectListItem>>();
foreach (var attribute in product.ProductAttributes.ToList())
{
Attributes.Add(attribute.DisplayName,
@ -55,13 +50,12 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
.Select(dto => new SelectListItem(dto.DisplayName, dto.Id.ToString())).ToList());
}
}
public virtual async Task<IActionResult> OnPostAsync()
{
var createDto = ObjectMapper.Map<CreateProductSkuViewModel, CreateProductSkuDto>(ProductSku);
createDto.AttributeOptionIds = SelectedAttributeOptionIdDict.Values.ToList();
if (ProductSku.ProductDetail.HasContent())
{
var detail = await _productDetailAppService.CreateAsync(
@ -70,15 +64,13 @@ namespace EasyAbp.EShop.Products.Web.Pages.EShop.Products.Products.ProductSku
createDto.ProductDetailId = detail.Id;
}
var product = await _productAppService.CreateSkuAsync(ProductId, createDto);
var productSku = product.ProductSkus
.Single(x => !x.AttributeOptionIds.Except(createDto.AttributeOptionIds).Any());
await _productInventoryAppService.UpdateAsync(new UpdateProductInventoryDto
await _productAppService.ChangeInventoryAsync(product.Id, productSku.Id, new ChangeProductInventoryDto
{
ProductId = product.Id,
ProductSkuId = productSku.Id,
ChangedInventory = ProductSku.Inventory
});

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

@ -1,26 +0,0 @@
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
}
}
}
Loading…
Cancel
Save