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