mirror of https://github.com/EasyAbp/EShop.git
committed by
GitHub
40 changed files with 5712 additions and 100 deletions
@ -1,17 +1,21 @@ |
|||
using System; |
|||
using EasyAbp.EShop.Products.Options.InventoryProviders; |
|||
using EasyAbp.EShop.Products.Options.ProductGroups; |
|||
using EasyAbp.EShop.Products.Products; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace EasyAbp.EShop.Products.Options |
|||
{ |
|||
public class EShopProductsOptions |
|||
{ |
|||
public ProductGroupConfigurations Groups { get; } |
|||
public ProductGroupConfigurations Groups { get; } = new(); |
|||
|
|||
public Type DefaultFileDownloadProviderType { get; set; } |
|||
|
|||
public EShopProductsOptions() |
|||
{ |
|||
Groups = new ProductGroupConfigurations(); |
|||
} |
|||
public InventoryProviderConfigurations InventoryProviders { get; } = new(); |
|||
|
|||
/// <summary>
|
|||
/// If the value is <c>null</c>, it will fall back to DefaultProductInventoryProviderName
|
|||
/// in the <see cref="DefaultProductInventoryProvider"/>.
|
|||
/// </summary>
|
|||
[CanBeNull] |
|||
public string DefaultInventoryProviderName { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace EasyAbp.EShop.Products.Options.InventoryProviders |
|||
{ |
|||
public interface IInventoryProviderConfigurationProvider |
|||
{ |
|||
InventoryProviderConfiguration Get(string providerName); |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
|
|||
namespace EasyAbp.EShop.Products.Options.InventoryProviders |
|||
{ |
|||
public class InventoryProviderConfiguration |
|||
{ |
|||
public string DisplayName { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
|
|||
public Type ProviderType { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EasyAbp.EShop.Products.Options.InventoryProviders |
|||
{ |
|||
public class InventoryProviderConfigurationProvider : IInventoryProviderConfigurationProvider, ITransientDependency |
|||
{ |
|||
private readonly EShopProductsOptions _options; |
|||
|
|||
public InventoryProviderConfigurationProvider(IOptions<EShopProductsOptions> options) |
|||
{ |
|||
_options = options.Value; |
|||
} |
|||
|
|||
public InventoryProviderConfiguration Get(string providerName) |
|||
{ |
|||
return _options.InventoryProviders.GetConfiguration(providerName); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Products.Options.InventoryProviders |
|||
{ |
|||
public class InventoryProviderConfigurations |
|||
{ |
|||
private readonly Dictionary<string, InventoryProviderConfiguration> _providers; |
|||
|
|||
public InventoryProviderConfigurations() |
|||
{ |
|||
_providers = new Dictionary<string, InventoryProviderConfiguration>(); |
|||
} |
|||
|
|||
public InventoryProviderConfigurations Configure( |
|||
[NotNull] string name, |
|||
[NotNull] Action<InventoryProviderConfiguration> configureAction) |
|||
{ |
|||
Check.NotNullOrWhiteSpace(name, nameof(name)); |
|||
Check.NotNull(configureAction, nameof(configureAction)); |
|||
|
|||
configureAction( |
|||
_providers.GetOrAdd( |
|||
name, |
|||
() => new InventoryProviderConfiguration() |
|||
) |
|||
); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public InventoryProviderConfigurations ConfigureAll( |
|||
Action<string, InventoryProviderConfiguration> configureAction) |
|||
{ |
|||
foreach (var provider in _providers) |
|||
{ |
|||
configureAction(provider.Key, provider.Value); |
|||
} |
|||
|
|||
return this; |
|||
} |
|||
|
|||
[NotNull] |
|||
public InventoryProviderConfiguration GetConfiguration([NotNull] string name) |
|||
{ |
|||
Check.NotNullOrWhiteSpace(name, nameof(name)); |
|||
|
|||
return _providers.GetOrDefault(name); |
|||
} |
|||
|
|||
[NotNull] |
|||
public Dictionary<string, InventoryProviderConfiguration> GetConfigurationsDictionary() |
|||
{ |
|||
return _providers; |
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +1,18 @@ |
|||
namespace EasyAbp.EShop.Products.Options.ProductGroups |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace EasyAbp.EShop.Products.Options.ProductGroups |
|||
{ |
|||
public class ProductGroupConfiguration |
|||
{ |
|||
public string DisplayName { get; set; } |
|||
|
|||
|
|||
public string Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// If the value is <c>null</c>, it will fall back to DefaultInventoryProviderName
|
|||
/// in the <see cref="EShopProductsOptions"/>.
|
|||
/// </summary>
|
|||
[CanBeNull] |
|||
public string DefaultInventoryProviderName { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Products.ProductInventories; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace EasyAbp.EShop.Products.Products; |
|||
|
|||
public interface IProductInventoryProviderResolver |
|||
{ |
|||
Task<bool> ExistProviderAsync([NotNull] string providerName); |
|||
|
|||
Task<IProductInventoryProvider> GetAsync(Product product); |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
using Volo.Abp; |
|||
|
|||
namespace EasyAbp.EShop.Products.Products |
|||
{ |
|||
public class NonexistentInventoryProviderException : BusinessException |
|||
{ |
|||
public NonexistentInventoryProviderException(string inventoryProviderName) : |
|||
base(ProductsErrorCodes.NonexistentInventoryProvider) |
|||
{ |
|||
WithData(nameof(inventoryProviderName), inventoryProviderName); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
using System; |
|||
using System.Collections.Concurrent; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Products.Options; |
|||
using EasyAbp.EShop.Products.ProductInventories; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EasyAbp.EShop.Products.Products; |
|||
|
|||
public class ProductInventoryProviderResolver : IProductInventoryProviderResolver, ITransientDependency |
|||
{ |
|||
protected static ConcurrentDictionary<string, Type> NameToProviderTypeMapping { get; } = new(); |
|||
|
|||
protected IServiceProvider ServiceProvider { get; } |
|||
|
|||
public ProductInventoryProviderResolver(IServiceProvider serviceProvider) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
} |
|||
|
|||
public virtual Task<bool> ExistProviderAsync(string providerName) |
|||
{ |
|||
TryBuildNameToProviderTypeMapping(); |
|||
|
|||
return Task.FromResult(NameToProviderTypeMapping.ContainsKey(providerName)); |
|||
} |
|||
|
|||
public virtual Task<IProductInventoryProvider> GetAsync(Product product) |
|||
{ |
|||
if (!product.InventoryProviderName.IsNullOrWhiteSpace()) |
|||
{ |
|||
return Task.FromResult(GetProviderByName(product.InventoryProviderName)); |
|||
} |
|||
|
|||
var options = ServiceProvider.GetRequiredService<IOptions<EShopProductsOptions>>(); |
|||
var productGroupConfiguration = options.Value.Groups.GetConfiguration(product.ProductGroupName); |
|||
|
|||
if (!productGroupConfiguration.DefaultInventoryProviderName.IsNullOrWhiteSpace()) |
|||
{ |
|||
return Task.FromResult(GetProviderByName(productGroupConfiguration.DefaultInventoryProviderName)); |
|||
} |
|||
|
|||
return Task.FromResult(GetProviderByName(options.Value.DefaultInventoryProviderName)); |
|||
} |
|||
|
|||
protected virtual IProductInventoryProvider GetProviderByName([CanBeNull] string providerName) |
|||
{ |
|||
if (providerName.IsNullOrEmpty()) |
|||
{ |
|||
providerName = DefaultProductInventoryProvider.DefaultProductInventoryProviderName; |
|||
} |
|||
|
|||
TryBuildNameToProviderTypeMapping(); |
|||
|
|||
var providerType = NameToProviderTypeMapping[providerName!]; |
|||
|
|||
return (IProductInventoryProvider)ServiceProvider.GetService(providerType); |
|||
} |
|||
|
|||
protected virtual void TryBuildNameToProviderTypeMapping() |
|||
{ |
|||
if (!NameToProviderTypeMapping.IsEmpty) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var options = ServiceProvider.GetRequiredService<IOptions<EShopProductsOptions>>().Value; |
|||
|
|||
foreach (var pair in options.InventoryProviders.GetConfigurationsDictionary()) |
|||
{ |
|||
NameToProviderTypeMapping[pair.Key] = pair.Value.ProviderType; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Products.ProductInventories; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EasyAbp.EShop.Products; |
|||
|
|||
public class FakeProductInventoryProvider : IProductInventoryProvider, ITransientDependency |
|||
{ |
|||
public string InventoryProviderName { get; } = "Fake"; |
|||
|
|||
private static InventoryDataModel Model { get; } = new() |
|||
{ |
|||
Inventory = 9998, |
|||
Sold = 0 |
|||
}; |
|||
|
|||
public Task<InventoryDataModel> GetInventoryDataAsync(InventoryQueryModel model) |
|||
{ |
|||
return Task.FromResult(Model); |
|||
} |
|||
|
|||
public Task<Dictionary<Guid, InventoryDataModel>> GetSkuIdInventoryDataMappingAsync( |
|||
IList<InventoryQueryModel> models) |
|||
{ |
|||
var result = new Dictionary<Guid, InventoryDataModel>(); |
|||
|
|||
foreach (var model in models) |
|||
{ |
|||
result.Add(model.ProductSkuId, Model); |
|||
} |
|||
|
|||
return Task.FromResult(result); |
|||
} |
|||
|
|||
public Task<bool> TryIncreaseInventoryAsync(InventoryQueryModel model, int quantity, bool decreaseSold) |
|||
{ |
|||
Model.Inventory++; |
|||
|
|||
if (decreaseSold) |
|||
{ |
|||
Model.Sold--; |
|||
} |
|||
|
|||
return Task.FromResult(true); |
|||
} |
|||
|
|||
public Task<bool> TryReduceInventoryAsync(InventoryQueryModel model, int quantity, bool increaseSold) |
|||
{ |
|||
Model.Inventory--; |
|||
|
|||
if (increaseSold) |
|||
{ |
|||
Model.Sold++; |
|||
} |
|||
|
|||
return Task.FromResult(true); |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,35 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace EShopSample.Migrations |
|||
{ |
|||
public partial class AddedInventoryProviderName : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "InventoryProviderName", |
|||
table: "EasyAbpEShopProductsProductViews", |
|||
type: "nvarchar(max)", |
|||
nullable: true); |
|||
|
|||
migrationBuilder.AddColumn<string>( |
|||
name: "InventoryProviderName", |
|||
table: "EasyAbpEShopProductsProducts", |
|||
type: "nvarchar(max)", |
|||
nullable: true); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "InventoryProviderName", |
|||
table: "EasyAbpEShopProductsProductViews"); |
|||
|
|||
migrationBuilder.DropColumn( |
|||
name: "InventoryProviderName", |
|||
table: "EasyAbpEShopProductsProducts"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue