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.Options.ProductGroups; |
||||
|
using EasyAbp.EShop.Products.Products; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
namespace EasyAbp.EShop.Products.Options |
namespace EasyAbp.EShop.Products.Options |
||||
{ |
{ |
||||
public class EShopProductsOptions |
public class EShopProductsOptions |
||||
{ |
{ |
||||
public ProductGroupConfigurations Groups { get; } |
public ProductGroupConfigurations Groups { get; } = new(); |
||||
|
|
||||
public Type DefaultFileDownloadProviderType { get; set; } |
public InventoryProviderConfigurations InventoryProviders { get; } = new(); |
||||
|
|
||||
public EShopProductsOptions() |
/// <summary>
|
||||
{ |
/// If the value is <c>null</c>, it will fall back to DefaultProductInventoryProviderName
|
||||
Groups = new ProductGroupConfigurations(); |
/// 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 class ProductGroupConfiguration |
||||
{ |
{ |
||||
public string DisplayName { get; set; } |
public string DisplayName { get; set; } |
||||
|
|
||||
public string Description { 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