Browse Source

Introduce CurrencyCode setting in the Orders module

Resolve #22
pull/178/head
gdlcf88 4 years ago
parent
commit
29cf960a5e
  1. 33
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs
  2. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/en.json
  3. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/zh-Hans.json
  4. 4
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/zh-Hant.json
  5. 21
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Settings/OrdersSettingDefinitionProvider.cs
  6. 2
      modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Settings/OrdersSettings.cs
  7. 61
      modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs

33
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/NewOrderGenerator.cs

@ -3,14 +3,17 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Orders.Orders.Dtos; using EasyAbp.EShop.Orders.Orders.Dtos;
using EasyAbp.EShop.Orders.Settings;
using EasyAbp.EShop.Products.ProductDetails.Dtos; using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos; using EasyAbp.EShop.Products.Products.Dtos;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.Settings;
using Volo.Abp.Timing; using Volo.Abp.Timing;
namespace EasyAbp.EShop.Orders.Orders namespace EasyAbp.EShop.Orders.Orders
@ -20,6 +23,7 @@ namespace EasyAbp.EShop.Orders.Orders
private readonly IClock _clock; private readonly IClock _clock;
private readonly IGuidGenerator _guidGenerator; private readonly IGuidGenerator _guidGenerator;
private readonly ICurrentTenant _currentTenant; private readonly ICurrentTenant _currentTenant;
private readonly ISettingProvider _settingProvider;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IOrderNumberGenerator _orderNumberGenerator; private readonly IOrderNumberGenerator _orderNumberGenerator;
private readonly IProductSkuDescriptionProvider _productSkuDescriptionProvider; private readonly IProductSkuDescriptionProvider _productSkuDescriptionProvider;
@ -29,6 +33,7 @@ namespace EasyAbp.EShop.Orders.Orders
IClock clock, IClock clock,
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
ISettingProvider settingProvider,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IOrderNumberGenerator orderNumberGenerator, IOrderNumberGenerator orderNumberGenerator,
IProductSkuDescriptionProvider productSkuDescriptionProvider, IProductSkuDescriptionProvider productSkuDescriptionProvider,
@ -37,6 +42,7 @@ namespace EasyAbp.EShop.Orders.Orders
_clock = clock; _clock = clock;
_guidGenerator = guidGenerator; _guidGenerator = guidGenerator;
_currentTenant = currentTenant; _currentTenant = currentTenant;
_settingProvider = settingProvider;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_orderNumberGenerator = orderNumberGenerator; _orderNumberGenerator = orderNumberGenerator;
_productSkuDescriptionProvider = productSkuDescriptionProvider; _productSkuDescriptionProvider = productSkuDescriptionProvider;
@ -53,16 +59,17 @@ namespace EasyAbp.EShop.Orders.Orders
orderLines.Add(await GenerateOrderLineAsync(input, inputOrderLine, productDict, productDetailDict)); orderLines.Add(await GenerateOrderLineAsync(input, inputOrderLine, productDict, productDetailDict));
} }
var storeCurrency = await GetStoreCurrencyAsync(input.StoreId); var effectiveCurrency = await GetEffectiveCurrencyAsync();
if (orderLines.Any(x => x.Currency != storeCurrency)) if (orderLines.Any(x => x.Currency != effectiveCurrency))
{ {
throw new UnexpectedCurrencyException(storeCurrency); throw new UnexpectedCurrencyException(effectiveCurrency);
} }
var productTotalPrice = orderLines.Select(x => x.TotalPrice).Sum(); var productTotalPrice = orderLines.Select(x => x.TotalPrice).Sum();
var paymentExpireIn = orderLines.Select(x => productDict[x.ProductId].GetSkuPaymentExpireIn(x.ProductSkuId)).Min(); var paymentExpireIn = orderLines.Select(x => productDict[x.ProductId].GetSkuPaymentExpireIn(x.ProductSkuId))
.Min();
var totalPrice = productTotalPrice; var totalPrice = productTotalPrice;
var totalDiscount = orderLines.Select(x => x.TotalDiscount).Sum(); var totalDiscount = orderLines.Select(x => x.TotalDiscount).Sum();
@ -72,7 +79,7 @@ namespace EasyAbp.EShop.Orders.Orders
tenantId: _currentTenant.Id, tenantId: _currentTenant.Id,
storeId: input.StoreId, storeId: input.StoreId,
customerUserId: customerUserId, customerUserId: customerUserId,
currency: storeCurrency, currency: effectiveCurrency,
productTotalPrice: productTotalPrice, productTotalPrice: productTotalPrice,
totalDiscount: totalDiscount, totalDiscount: totalDiscount,
totalPrice: totalPrice, totalPrice: totalPrice,
@ -124,7 +131,7 @@ namespace EasyAbp.EShop.Orders.Orders
} }
var unitPrice = await GetUnitPriceAsync(input, inputOrderLine, product, productSku); var unitPrice = await GetUnitPriceAsync(input, inputOrderLine, product, productSku);
var totalPrice = unitPrice * inputOrderLine.Quantity; var totalPrice = unitPrice * inputOrderLine.Quantity;
var orderLine = new OrderLine( var orderLine = new OrderLine(
@ -148,7 +155,7 @@ namespace EasyAbp.EShop.Orders.Orders
actualTotalPrice: totalPrice, actualTotalPrice: totalPrice,
quantity: inputOrderLine.Quantity quantity: inputOrderLine.Quantity
); );
inputOrderLine.MapExtraPropertiesTo(orderLine, MappingPropertyDefinitionChecks.Destination); inputOrderLine.MapExtraPropertiesTo(orderLine, MappingPropertyDefinitionChecks.Destination);
return orderLine; return orderLine;
@ -171,10 +178,14 @@ namespace EasyAbp.EShop.Orders.Orders
return productSku.Price; return productSku.Price;
} }
protected virtual Task<string> GetStoreCurrencyAsync(Guid storeId) protected virtual async Task<string> GetEffectiveCurrencyAsync()
{ {
// Todo: Get real store currency configuration. var currencyCode = Check.NotNullOrWhiteSpace(
return Task.FromResult("USD"); await _settingProvider.GetOrNullAsync(OrdersSettings.CurrencyCode),
nameof(OrdersSettings.CurrencyCode)
);
return currencyCode;
} }
} }
} }

4
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/en.json

@ -53,6 +53,8 @@
"EasyAbp.EShop.Orders:InvalidRefundAmount": "The refund amount ({amount}) is invalid.", "EasyAbp.EShop.Orders:InvalidRefundAmount": "The refund amount ({amount}) is invalid.",
"EasyAbp.EShop.Orders:InvalidRefundQuantity": "The refund quantity ({quantity}) is invalid.", "EasyAbp.EShop.Orders:InvalidRefundQuantity": "The refund quantity ({quantity}) is invalid.",
"EasyAbp.EShop.Orders:OrderIsInWrongStage": "The order {orderId} is in the wrong stage.", "EasyAbp.EShop.Orders:OrderIsInWrongStage": "The order {orderId} is in the wrong stage.",
"EasyAbp.EShop.Orders:ExistFlashSalesProduct": "Exist unexpected flash-sales product" "EasyAbp.EShop.Orders:ExistFlashSalesProduct": "Exist unexpected flash-sales product",
"DisplayName:EasyAbp.EShop.Orders.CurrencyCode": "Currency code",
"Description:EasyAbp.EShop.Orders.CurrencyCode": "ISO 4217 code (see https://en.wikipedia.org/wiki/ISO_4217)"
} }
} }

4
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/zh-Hans.json

@ -53,6 +53,8 @@
"EasyAbp.EShop.Orders:InvalidRefundAmount": "退款金额({amount})无效", "EasyAbp.EShop.Orders:InvalidRefundAmount": "退款金额({amount})无效",
"EasyAbp.EShop.Orders:InvalidRefundQuantity": "退款数量({quantity})无效", "EasyAbp.EShop.Orders:InvalidRefundQuantity": "退款数量({quantity})无效",
"EasyAbp.EShop.Orders:OrderIsInWrongStage": "订单{orderId}处于错误的阶段", "EasyAbp.EShop.Orders:OrderIsInWrongStage": "订单{orderId}处于错误的阶段",
"EasyAbp.EShop.Orders:ExistFlashSalesProduct": "清单中不允许存在闪购产品" "EasyAbp.EShop.Orders:ExistFlashSalesProduct": "清单中不允许存在闪购产品",
"DisplayName:EasyAbp.EShop.Orders.CurrencyCode": "货币代码",
"Description:EasyAbp.EShop.Orders.CurrencyCode": "ISO 4217 货币代码 (详见 https://en.wikipedia.org/wiki/ISO_4217)"
} }
} }

4
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/zh-Hant.json

@ -53,6 +53,8 @@
"EasyAbp.EShop.Orders:InvalidRefundAmount": "退款金額({amount})無效", "EasyAbp.EShop.Orders:InvalidRefundAmount": "退款金額({amount})無效",
"EasyAbp.EShop.Orders:InvalidRefundQuantity": "退款數量({quantity})無效", "EasyAbp.EShop.Orders:InvalidRefundQuantity": "退款數量({quantity})無效",
"EasyAbp.EShop.Orders:OrderIsInWrongStage": "訂單{orderId}處於錯誤的階段", "EasyAbp.EShop.Orders:OrderIsInWrongStage": "訂單{orderId}處於錯誤的階段",
"EasyAbp.EShop.Orders:ExistFlashSalesProduct": "清單中不允許存在閃購產品" "EasyAbp.EShop.Orders:ExistFlashSalesProduct": "清單中不允許存在閃購產品",
"DisplayName:EasyAbp.EShop.Orders.CurrencyCode": "貨幣代碼",
"Description:EasyAbp.EShop.Orders.CurrencyCode": "ISO 4217 貨幣代碼 (詳見 https://en.wikipedia.org/wiki/ISO_4217)"
} }
} }

21
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Settings/OrdersSettingDefinitionProvider.cs

@ -1,14 +1,33 @@
using Volo.Abp.Settings; using EasyAbp.EShop.Orders.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
namespace EasyAbp.EShop.Orders.Settings namespace EasyAbp.EShop.Orders.Settings
{ {
public class OrdersSettingDefinitionProvider : SettingDefinitionProvider public class OrdersSettingDefinitionProvider : SettingDefinitionProvider
{ {
public static string DefaultCurrency { get; set; } = "USD";
public override void Define(ISettingDefinitionContext context) public override void Define(ISettingDefinitionContext context)
{ {
/* Define module settings here. /* Define module settings here.
* Use names from OrdersSettings class. * Use names from OrdersSettings class.
*/ */
context.Add(
new SettingDefinition(
OrdersSettings.CurrencyCode,
DefaultCurrency,
L($"DisplayName:{OrdersSettings.CurrencyCode}"),
L($"Description:{OrdersSettings.CurrencyCode}"),
isVisibleToClients: true
)
);
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<OrdersResource>(name);
} }
} }
} }

2
modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Settings/OrdersSettings.cs

@ -7,5 +7,7 @@
/* Add constants for setting names. Example: /* Add constants for setting names. Example:
* public const string MySettingName = GroupName + ".MySettingName"; * public const string MySettingName = GroupName + ".MySettingName";
*/ */
public const string CurrencyCode = GroupName + ".CurrencyCode";
} }
} }

61
modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EasyAbp.EShop.Orders.Orders.Dtos; using EasyAbp.EShop.Orders.Orders.Dtos;
using EasyAbp.EShop.Orders.Settings;
using EasyAbp.EShop.Products.ProductDetails; using EasyAbp.EShop.Products.ProductDetails;
using EasyAbp.EShop.Products.ProductDetails.Dtos; using EasyAbp.EShop.Products.ProductDetails.Dtos;
using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products;
@ -12,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection;
using NSubstitute; using NSubstitute;
using Shouldly; using Shouldly;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Settings;
using Volo.Abp.Timing; using Volo.Abp.Timing;
using Xunit; using Xunit;
@ -532,17 +534,62 @@ namespace EasyAbp.EShop.Orders.Orders
} }
}; };
Product1.InventoryStrategy = InventoryStrategy.FlashSales; try
{
Product1.InventoryStrategy = InventoryStrategy.FlashSales;
await WithUnitOfWorkAsync(async () => await WithUnitOfWorkAsync(async () =>
{
var exception =
await Should.ThrowAsync<BusinessException>(() => _orderAppService.CreateAsync(createOrderDto));
exception.Code.ShouldBe(OrdersErrorCodes.ExistFlashSalesProduct);
});
Product1.InventoryStrategy = InventoryStrategy.NoNeed;
}
catch
{ {
var exception = Product1.InventoryStrategy = InventoryStrategy.NoNeed;
await Should.ThrowAsync<BusinessException>(() => _orderAppService.CreateAsync(createOrderDto)); throw;
}
}
exception.Code.ShouldBe(OrdersErrorCodes.ExistFlashSalesProduct); [Fact]
}); public async Task Should_Throw_If_Product_Sku_Uses_Unexpected_Currency()
{
var createOrderDto = new CreateOrderDto
{
StoreId = OrderTestData.Store1Id,
OrderLines = new List<CreateOrderLineDto>
{
new()
{
ProductId = OrderTestData.Product1Id,
ProductSkuId = OrderTestData.ProductSku1Id,
Quantity = 1
}
}
};
try
{
OrdersSettingDefinitionProvider.DefaultCurrency = "CNY"; // The effective value is "USD"
await WithUnitOfWorkAsync(async () =>
{
var exception =
await Should.ThrowAsync<BusinessException>(() => _orderAppService.CreateAsync(createOrderDto));
Product1.InventoryStrategy = InventoryStrategy.NoNeed; exception.Code.ShouldBe(OrdersErrorCodes.UnexpectedCurrency);
});
OrdersSettingDefinitionProvider.DefaultCurrency = "USD";
}
catch
{
OrdersSettingDefinitionProvider.DefaultCurrency = "USD";
throw;
}
} }
} }
} }
Loading…
Cancel
Save