mirror of https://github.com/EasyAbp/EShop.git
Browse Source
Close #79 Remove CreatePaymentEto in PaymentCreationResource Fix BasicPaymentCreationAuthorizationHandlerpull/103/head
19 changed files with 181 additions and 168 deletions
@ -0,0 +1,53 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using EasyAbp.EShop.Orders.Orders.Dtos; |
||||
|
using EasyAbp.EShop.Products.Products; |
||||
|
using EasyAbp.EShop.Products.Products.Dtos; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
public class BasicOrderCreationAuthorizationHandler : OrderCreationAuthorizationHandler |
||||
|
{ |
||||
|
protected override async Task HandleOrderCreationAsync(AuthorizationHandlerContext context, |
||||
|
OrderOperationAuthorizationRequirement requirement, OrderCreationResource resource) |
||||
|
{ |
||||
|
if (!await IsProductsPublishedAsync(resource.Input, resource.ProductDictionary)) |
||||
|
{ |
||||
|
context.Fail(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!await IsInventoriesSufficientAsync(resource.Input, resource.ProductDictionary)) |
||||
|
{ |
||||
|
context.Fail(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
context.Succeed(requirement); |
||||
|
} |
||||
|
|
||||
|
protected virtual Task<bool> IsProductsPublishedAsync(CreateOrderDto input, |
||||
|
Dictionary<Guid, ProductDto> productDictionary) |
||||
|
{ |
||||
|
return Task.FromResult( |
||||
|
input.OrderLines.Select(dto => dto.ProductId).Distinct().ToArray() |
||||
|
.All(productId => productDictionary[productId].IsPublished) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
protected virtual Task<bool> IsInventoriesSufficientAsync(CreateOrderDto input, |
||||
|
Dictionary<Guid, ProductDto> productDictionary) |
||||
|
{ |
||||
|
return Task.FromResult( |
||||
|
!(from orderLine in input.OrderLines |
||||
|
let product = productDictionary[orderLine.ProductId] |
||||
|
let inventory = product.ProductSkus.Single(sku => sku.Id == orderLine.ProductSkuId).Inventory |
||||
|
where product.InventoryStrategy != InventoryStrategy.NoNeed && inventory < orderLine.Quantity |
||||
|
select orderLine).Any() |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,55 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Threading.Tasks; |
|
||||
using EasyAbp.EShop.Orders.Orders.Dtos; |
|
||||
using EasyAbp.EShop.Products.Products; |
|
||||
using EasyAbp.EShop.Products.Products.Dtos; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Orders.Orders |
|
||||
{ |
|
||||
public class BasicPurchasableCheckProvider : IPurchasableCheckProvider, ITransientDependency |
|
||||
{ |
|
||||
public virtual async Task CheckAsync(CreateOrderDto input, Dictionary<Guid, ProductDto> productDict, |
|
||||
Dictionary<string, object> orderExtraProperties) |
|
||||
{ |
|
||||
await CheckProductsPublishedAsync(input, productDict); |
|
||||
|
|
||||
await CheckInventoriesSufficientAsync(input, productDict); |
|
||||
} |
|
||||
|
|
||||
protected virtual Task CheckProductsPublishedAsync(CreateOrderDto input, |
|
||||
Dictionary<Guid, ProductDto> productDict) |
|
||||
{ |
|
||||
foreach (var productId in input.OrderLines.Select(dto => dto.ProductId).Distinct().ToArray()) |
|
||||
{ |
|
||||
if (!productDict[productId].IsPublished) |
|
||||
{ |
|
||||
throw new NotPurchasableException(productId, null, "Unpublished project"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
|
|
||||
protected virtual Task CheckInventoriesSufficientAsync(CreateOrderDto input, |
|
||||
Dictionary<Guid, ProductDto> productDict) |
|
||||
{ |
|
||||
foreach (var orderLine in input.OrderLines) |
|
||||
{ |
|
||||
var product = productDict[orderLine.ProductId]; |
|
||||
var inventory = product.ProductSkus |
|
||||
.Single(sku => sku.Id == orderLine.ProductSkuId).Inventory; |
|
||||
|
|
||||
if (product.InventoryStrategy != InventoryStrategy.NoNeed && inventory < orderLine.Quantity) |
|
||||
{ |
|
||||
throw new NotPurchasableException(orderLine.ProductId, orderLine.ProductSkuId, |
|
||||
"Insufficient inventory"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
public class CurrencyIsLimitException : BusinessException |
||||
|
{ |
||||
|
public CurrencyIsLimitException(string expectedCurrency) : base( |
||||
|
"CurrencyIsLimit", |
||||
|
$"Only the specified currency {expectedCurrency} is allowed.") |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,14 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using EasyAbp.EShop.Orders.Orders.Dtos; |
|
||||
using EasyAbp.EShop.Products.Products.Dtos; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Orders.Orders |
|
||||
{ |
|
||||
public interface IPurchasableCheckProvider |
|
||||
{ |
|
||||
Task CheckAsync(CreateOrderDto input, Dictionary<Guid, ProductDto> productDict, |
|
||||
Dictionary<string, object> orderExtraProperties); |
|
||||
} |
|
||||
} |
|
||||
@ -1,14 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using EasyAbp.EShop.Orders.Orders.Dtos; |
|
||||
using EasyAbp.EShop.Products.Products.Dtos; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Orders.Orders |
|
||||
{ |
|
||||
public interface IPurchasableChecker |
|
||||
{ |
|
||||
Task CheckAsync(CreateOrderDto input, Dictionary<Guid, ProductDto> productDict, |
|
||||
Dictionary<string, object> orderExtraProperties); |
|
||||
} |
|
||||
} |
|
||||
@ -1,13 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Orders.Orders |
|
||||
{ |
|
||||
public class NotPurchasableException : BusinessException |
|
||||
{ |
|
||||
public NotPurchasableException(Guid productId, Guid? productSkuId, string reason) : base( |
|
||||
message: $"Product {productId} (SKU: {productSkuId}) cannot be purchased, the reason is: {reason}") |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,22 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
public abstract class OrderCreationAuthorizationHandler : AuthorizationHandler<OrderOperationAuthorizationRequirement, OrderCreationResource> |
||||
|
{ |
||||
|
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OrderOperationAuthorizationRequirement requirement, |
||||
|
OrderCreationResource resource) |
||||
|
{ |
||||
|
if (requirement.OrderOperation != OrderOperation.Creation) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
await HandleOrderCreationAsync(context, requirement, resource); |
||||
|
} |
||||
|
|
||||
|
protected abstract Task HandleOrderCreationAsync(AuthorizationHandlerContext context, |
||||
|
OrderOperationAuthorizationRequirement requirement, OrderCreationResource resource); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using EasyAbp.EShop.Orders.Orders.Dtos; |
||||
|
using EasyAbp.EShop.Products.Products.Dtos; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
public class OrderCreationResource |
||||
|
{ |
||||
|
public CreateOrderDto Input { get; set; } |
||||
|
|
||||
|
public Dictionary<Guid, ProductDto> ProductDictionary { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
[Flags] |
||||
|
public enum OrderOperation |
||||
|
{ |
||||
|
Creation = 0 |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
public class OrderOperationAuthorizationRequirement : IAuthorizationRequirement |
||||
|
{ |
||||
|
public OrderOperation OrderOperation { get; } |
||||
|
|
||||
|
public OrderOperationAuthorizationRequirement(OrderOperation orderOperation) |
||||
|
{ |
||||
|
OrderOperation = orderOperation; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,31 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using EasyAbp.EShop.Orders.Orders.Dtos; |
|
||||
using EasyAbp.EShop.Products.Products.Dtos; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Orders.Orders |
|
||||
{ |
|
||||
public class PurchasableChecker : IPurchasableChecker, ITransientDependency |
|
||||
{ |
|
||||
private readonly IServiceProvider _serviceProvider; |
|
||||
|
|
||||
public PurchasableChecker(IServiceProvider serviceProvider) |
|
||||
{ |
|
||||
_serviceProvider = serviceProvider; |
|
||||
} |
|
||||
|
|
||||
public virtual async Task CheckAsync(CreateOrderDto input, Dictionary<Guid, ProductDto> productDict, |
|
||||
Dictionary<string, object> orderExtraProperties) |
|
||||
{ |
|
||||
var providers = _serviceProvider.GetServices<IPurchasableCheckProvider>(); |
|
||||
|
|
||||
foreach (var provider in providers) |
|
||||
{ |
|
||||
await provider.CheckAsync(input, productDict, orderExtraProperties); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue