mirror of https://github.com/EasyAbp/EShop.git
15 changed files with 195 additions and 66 deletions
@ -0,0 +1,17 @@ |
|||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
public class CheckProductPurchasableResult |
||||
|
{ |
||||
|
public bool IsPurchasable { get; set; } |
||||
|
|
||||
|
public string Reason { get; set; } |
||||
|
|
||||
|
public CheckProductPurchasableResult( |
||||
|
bool isPurchasable, |
||||
|
string reason = null) |
||||
|
{ |
||||
|
IsPurchasable = isPurchasable; |
||||
|
Reason = reason; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,9 +0,0 @@ |
|||||
namespace EasyAbp.EShop.Products.Products |
|
||||
{ |
|
||||
public class GetProductPurchasableStatusResult |
|
||||
{ |
|
||||
public ProductPurchasableStatus PurchasableStatus { get; set; } |
|
||||
|
|
||||
public string Reason { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -1,8 +0,0 @@ |
|||||
namespace EasyAbp.EShop.Products.Products |
|
||||
{ |
|
||||
public enum ProductPurchasableStatus |
|
||||
{ |
|
||||
CanBePurchased = 1, |
|
||||
CanNotBePurchased = 2 |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,51 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
public class BasicProductPurchasableCheckHandler : IProductPurchasableCheckHandler, ITransientDependency |
||||
|
{ |
||||
|
private readonly IProductInventoryProvider _productInventoryProvider; |
||||
|
|
||||
|
public BasicProductPurchasableCheckHandler( |
||||
|
IProductInventoryProvider productInventoryProvider) |
||||
|
{ |
||||
|
_productInventoryProvider = productInventoryProvider; |
||||
|
} |
||||
|
|
||||
|
public async Task<CheckProductPurchasableResult> CheckAsync(Product product, ProductSku productSku, Guid storeId, |
||||
|
Dictionary<string, object> extraProperties) |
||||
|
{ |
||||
|
if (!await IsProductPublishedAsync(product)) |
||||
|
{ |
||||
|
return new CheckProductPurchasableResult(false, "Unpublished project"); |
||||
|
} |
||||
|
|
||||
|
if (!await IsInventorySufficientAsync(product, productSku, storeId, extraProperties)) |
||||
|
{ |
||||
|
return new CheckProductPurchasableResult(false, "Insufficient inventory"); |
||||
|
} |
||||
|
|
||||
|
return new CheckProductPurchasableResult(true); |
||||
|
} |
||||
|
|
||||
|
protected virtual Task<bool> IsProductPublishedAsync(Product product) |
||||
|
{ |
||||
|
return Task.FromResult(product.IsPublished); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, Dictionary<string, object> extraProperties) |
||||
|
{ |
||||
|
if (!extraProperties.TryGetValue("Quantity", out var quantity)) |
||||
|
{ |
||||
|
throw new ProductPurchasableCheckHandlerMissingPropertyException( |
||||
|
nameof(BasicProductPurchasableCheckHandler), "Quantity"); |
||||
|
} |
||||
|
|
||||
|
return await _productInventoryProvider.IsInventorySufficientAsync(product, productSku, storeId, |
||||
|
Convert.ToInt32(quantity)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
[Dependency(TryRegister = true)] |
||||
|
public class DefaultProductInventoryProvider : IProductInventoryProvider, ITransientDependency |
||||
|
{ |
||||
|
public virtual async Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, int quantity) |
||||
|
{ |
||||
|
var inventory = await GetInventoryAsync(product, productSku, storeId); |
||||
|
|
||||
|
return product.InventoryStrategy == InventoryStrategy.NoNeed || inventory - quantity >= 0; |
||||
|
} |
||||
|
|
||||
|
public virtual Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId) |
||||
|
{ |
||||
|
return Task.FromResult(productSku.Inventory); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
public interface IProductInventoryProvider |
||||
|
{ |
||||
|
Task<bool> IsInventorySufficientAsync(Product product, ProductSku productSku, Guid storeId, int quantity); |
||||
|
|
||||
|
Task<int> GetInventoryAsync(Product product, ProductSku productSku, Guid storeId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
public interface IProductManager : IDomainService |
||||
|
{ |
||||
|
Task CheckPurchasableAsync(Product product, ProductSku productSku, Guid storeId, |
||||
|
Dictionary<string, object> extraProperties); |
||||
|
|
||||
|
Task<CheckProductPurchasableResult> GetPurchasableStatusAsync(Product product, ProductSku productSku, |
||||
|
Guid storeId, Dictionary<string, object> extraProperties); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
public interface IProductPurchasableCheckHandler |
||||
|
{ |
||||
|
Task<CheckProductPurchasableResult> CheckAsync(Product product, ProductSku productSku, Guid storeId, |
||||
|
Dictionary<string, object> extraProperties); |
||||
|
} |
||||
|
} |
||||
@ -1,13 +0,0 @@ |
|||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Products.Products |
|
||||
{ |
|
||||
public interface IProductPurchasableStatusProvider |
|
||||
{ |
|
||||
Task CheckPurchasableAsync(Product product, ProductSku productSku, Guid storeId); |
|
||||
|
|
||||
Task<GetProductPurchasableStatusResult> GetPurchasableStatusAsync(Product product, ProductSku productSku, |
|
||||
Guid storeId); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,40 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
public class ProductManager : DomainService, IProductManager |
||||
|
{ |
||||
|
public async Task CheckPurchasableAsync(Product product, ProductSku productSku, Guid storeId, |
||||
|
Dictionary<string, object> extraProperties) |
||||
|
{ |
||||
|
var result = await GetPurchasableStatusAsync(product, productSku, storeId, extraProperties); |
||||
|
|
||||
|
if (!result.IsPurchasable) |
||||
|
{ |
||||
|
throw new ProductIsNotPurchasableException(product.Id, result.Reason); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public async Task<CheckProductPurchasableResult> GetPurchasableStatusAsync(Product product, |
||||
|
ProductSku productSku, Guid storeId, Dictionary<string, object> extraProperties) |
||||
|
{ |
||||
|
var handlers = ServiceProvider.GetServices<IProductPurchasableCheckHandler>(); |
||||
|
|
||||
|
foreach (var handler in handlers) |
||||
|
{ |
||||
|
var result = await handler.CheckAsync(product, productSku, storeId, extraProperties); |
||||
|
|
||||
|
if (!result.IsPurchasable) |
||||
|
{ |
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return new CheckProductPurchasableResult(true); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products |
||||
|
{ |
||||
|
public class ProductPurchasableCheckHandlerMissingPropertyException : BusinessException |
||||
|
{ |
||||
|
public ProductPurchasableCheckHandlerMissingPropertyException(string handlerName, string propertyKey) : base( |
||||
|
message: $"The {handlerName} is missing extra property: {propertyKey}") |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,29 +0,0 @@ |
|||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Products.Products |
|
||||
{ |
|
||||
public class ProductPurchasableStatusProvider : IProductPurchasableStatusProvider, ITransientDependency |
|
||||
{ |
|
||||
public async Task CheckPurchasableAsync(Product product, ProductSku productSku, Guid storeId) |
|
||||
{ |
|
||||
var result = await GetPurchasableStatusAsync(product, productSku, storeId); |
|
||||
|
|
||||
if (result.PurchasableStatus != ProductPurchasableStatus.CanBePurchased) |
|
||||
{ |
|
||||
throw new ProductIsNotPurchasableException(product.Id, result.Reason); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public async Task<GetProductPurchasableStatusResult> GetPurchasableStatusAsync(Product product, ProductSku productSku, Guid storeId) |
|
||||
{ |
|
||||
// Todo: Determine whether the product can be purchased.
|
|
||||
return new GetProductPurchasableStatusResult |
|
||||
{ |
|
||||
PurchasableStatus = ProductPurchasableStatus.CanBePurchased, |
|
||||
Reason = null |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue