diff --git a/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EasyAbp.EShop.EntityFrameworkCore.Tests.csproj b/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EasyAbp.EShop.EntityFrameworkCore.Tests.csproj
index 821710c3..86e49d55 100644
--- a/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EasyAbp.EShop.EntityFrameworkCore.Tests.csproj
+++ b/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EasyAbp.EShop.EntityFrameworkCore.Tests.csproj
@@ -7,11 +7,10 @@
-
-
+
diff --git a/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopEntityFrameworkCoreTestModule.cs b/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopEntityFrameworkCoreTestModule.cs
index 9b851b97..30d9612c 100644
--- a/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopEntityFrameworkCoreTestModule.cs
+++ b/integration/EasyAbp.EShop/test/EasyAbp.EShop.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopEntityFrameworkCoreTestModule.cs
@@ -3,14 +3,16 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.Modularity;
namespace EasyAbp.EShop.EntityFrameworkCore
{
[DependsOn(
typeof(EShopTestBaseModule),
- typeof(EShopEntityFrameworkCoreModule)
- )]
+ typeof(EShopEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCoreSqliteModule)
+ )]
public class EShopEntityFrameworkCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/en.json b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/en.json
index 75fe3af4..6c004aef 100644
--- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/en.json
+++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Localization/Orders/en.json
@@ -61,7 +61,7 @@
"OrderExtraFeeRefundAmount": "Refund amount",
"EasyAbp.EShop.Orders:UnexpectedCurrency": "Only the specified currency {expectedCurrency} is allowed.",
"EasyAbp.EShop.Orders:OrderLineInvalidQuantity": "Invalid quantity {quantity} for product {productId} (SKU: {productSkuId}).",
- "EasyAbp.EShop.Orders:DiscountAmountOverflow": "The discount amount overflow.",
+ "EasyAbp.EShop.Orders:DiscountAmountOverflow": "The discount amount overflows.",
"EasyAbp.EShop.Orders:DuplicateOrderDiscount": "The discount {discountName} (key: {discountKey}) of order line {orderLineId} already exists.",
"EasyAbp.EShop.Orders:DuplicateOrderExtraFee": "The extra fee {extraFeeName} (key: {extraFeeKey}) already exists.",
"EasyAbp.EShop.Orders:InvalidOrderExtraFee": "The extra fee {extraFee} is invalid.",
diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderDiscountInfoModel.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Orders/OrderDiscountInfoModel.cs
similarity index 69%
rename from modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderDiscountInfoModel.cs
rename to modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Orders/OrderDiscountInfoModel.cs
index 0e0aec48..d085c36c 100644
--- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain/EasyAbp/EShop/Orders/Orders/OrderDiscountInfoModel.cs
+++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Domain.Shared/EasyAbp/EShop/Orders/Orders/OrderDiscountInfoModel.cs
@@ -1,4 +1,5 @@
using System;
+using EasyAbp.EShop.Products.Products;
using JetBrains.Annotations;
namespace EasyAbp.EShop.Orders.Orders;
@@ -18,16 +19,12 @@ public class OrderDiscountInfoModel
public decimal DiscountedAmount { get; set; }
- public OrderDiscountInfoModel(
- Guid orderLineId,
- [NotNull] string name,
- [CanBeNull] string key,
- [CanBeNull] string displayName,
- decimal discountedAmount)
+ public OrderDiscountInfoModel(Guid orderLineId, [NotNull] string name, [CanBeNull] string key,
+ [CanBeNull] string displayName, decimal discountedAmount)
{
OrderLineId = orderLineId;
Name = name;
- Key = key ?? string.Empty;
+ Key = key;
DisplayName = displayName;
DiscountedAmount = discountedAmount;
}
diff --git a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests.csproj b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests.csproj
index 78869d99..c56c823b 100644
--- a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests.csproj
+++ b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests.csproj
@@ -7,11 +7,10 @@
-
-
+
diff --git a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopOrdersEntityFrameworkCoreTestModule.cs b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopOrdersEntityFrameworkCoreTestModule.cs
index 3c038946..f4ef196d 100644
--- a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopOrdersEntityFrameworkCoreTestModule.cs
+++ b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopOrdersEntityFrameworkCoreTestModule.cs
@@ -3,14 +3,16 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.Modularity;
namespace EasyAbp.EShop.Orders.EntityFrameworkCore
{
[DependsOn(
typeof(EShopOrdersTestBaseModule),
- typeof(EShopOrdersEntityFrameworkCoreModule)
- )]
+ typeof(EShopOrdersEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCoreSqliteModule)
+ )]
public class EShopOrdersEntityFrameworkCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests.csproj b/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests.csproj
index 9600131d..d825db46 100644
--- a/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests.csproj
+++ b/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests.csproj
@@ -7,11 +7,10 @@
-
-
+
diff --git a/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPaymentsEntityFrameworkCoreTestModule.cs b/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPaymentsEntityFrameworkCoreTestModule.cs
index 9cbabbba..34d5add7 100644
--- a/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPaymentsEntityFrameworkCoreTestModule.cs
+++ b/modules/EasyAbp.EShop.Payments/test/EasyAbp.EShop.Payments.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPaymentsEntityFrameworkCoreTestModule.cs
@@ -3,14 +3,16 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.Modularity;
namespace EasyAbp.EShop.Payments.EntityFrameworkCore
{
[DependsOn(
typeof(EShopPaymentsTestBaseModule),
- typeof(EShopPaymentsEntityFrameworkCoreModule)
- )]
+ typeof(EShopPaymentsEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCoreSqliteModule)
+ )]
public class EShopPaymentsEntityFrameworkCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests.csproj b/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests.csproj
index 0d165405..44f16a77 100644
--- a/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests.csproj
+++ b/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests.csproj
@@ -7,11 +7,10 @@
-
-
+
diff --git a/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPluginsEntityFrameworkCoreTestModule.cs b/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPluginsEntityFrameworkCoreTestModule.cs
index 40e31822..1bf1d851 100644
--- a/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPluginsEntityFrameworkCoreTestModule.cs
+++ b/modules/EasyAbp.EShop.Plugins/test/EasyAbp.EShop.Plugins.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopPluginsEntityFrameworkCoreTestModule.cs
@@ -3,14 +3,16 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.Modularity;
namespace EasyAbp.EShop.Plugins.EntityFrameworkCore
{
[DependsOn(
typeof(EShopPluginsTestBaseModule),
- typeof(EShopPluginsEntityFrameworkCoreModule)
- )]
+ typeof(EShopPluginsEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCoreSqliteModule)
+ )]
public class EShopPluginsEntityFrameworkCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs
index 21e8686c..e183ccfe 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductSkuDto.cs
@@ -1,36 +1,40 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
-using Volo.Abp.Data;
namespace EasyAbp.EShop.Products.Products.Dtos
{
[Serializable]
- public class ProductSkuDto : ExtensibleFullAuditedEntityDto, IProductSku
+ public class ProductSkuDto : ExtensibleFullAuditedEntityDto, IProductSku, IHasFullDiscountsInfo
{
public List AttributeOptionIds { get; set; }
+
public string Name { get; set; }
-
+
public string Currency { get; set; }
-
+
public decimal? OriginalPrice { get; set; }
-
+
+ public decimal PriceWithoutDiscount { get; set; }
+
public decimal Price { get; set; }
-
- public decimal DiscountedPrice { get; set; }
-
+
+ public List ProductDiscounts { get; set; } = new();
+
+ public List OrderDiscountPreviews { get; set; } = new();
+
public int Inventory { get; set; }
-
+
public long Sold { get; set; }
-
+
public int OrderMinQuantity { get; set; }
-
+
public int OrderMaxQuantity { get; set; }
-
+
public TimeSpan? PaymentExpireIn { get; set; }
public string MediaResources { get; set; }
-
+
public Guid? ProductDetailId { get; set; }
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductViewDto.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductViewDto.cs
index 6de98b2e..87ade88b 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductViewDto.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application.Contracts/EasyAbp/EShop/Products/Products/Dtos/ProductViewDto.cs
@@ -1,15 +1,18 @@
using System;
+using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Products.Products.Dtos
{
[Serializable]
- public class ProductViewDto : ExtensibleCreationAuditedEntityDto, IProductBase, IHasProductGroupDisplayName
+ public class ProductViewDto : ExtensibleCreationAuditedEntityDto, IProductView
{
public Guid StoreId { get; set; }
public string ProductGroupName { get; set; }
+ public string ProductGroupDisplayName { get; set; }
+
public Guid? ProductDetailId { get; set; }
public string UniqueName { get; set; }
@@ -38,8 +41,16 @@ namespace EasyAbp.EShop.Products.Products.Dtos
public decimal? MaximumPrice { get; set; }
+ public decimal? MinimumPriceWithoutDiscount { get; set; }
+
+ public decimal? MaximumPriceWithoutDiscount { get; set; }
+
public long Sold { get; set; }
- public string ProductGroupDisplayName { get; set; }
+ public decimal PriceWithoutDiscount { get; set; }
+
+ public List ProductDiscounts { get; set; } = new();
+
+ public List OrderDiscountPreviews { get; set; } = new();
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
index d665704a..b2496bc9 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductAppService.cs
@@ -312,8 +312,10 @@ namespace EasyAbp.EShop.Products.Products
var priceDataModel = await _productManager.GetRealPriceAsync(product, productSku);
- productSkuDto.Price = priceDataModel.Price;
- productSkuDto.DiscountedPrice = priceDataModel.DiscountedPrice;
+ productSkuDto.PriceWithoutDiscount = priceDataModel.PriceWithoutDiscount;
+ productSkuDto.Price = priceDataModel.DiscountedPrice;
+ productSkuDto.ProductDiscounts = priceDataModel.ProductDiscounts;
+ productSkuDto.OrderDiscountPreviews = priceDataModel.OrderDiscountPreviews;
}
if (productDto.ProductSkus.Count > 0)
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductViewAppService.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductViewAppService.cs
index 69a83754..e9235266 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductViewAppService.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/Products/ProductViewAppService.cs
@@ -9,7 +9,6 @@ using EasyAbp.EShop.Products.Settings;
using EasyAbp.EShop.Stores.Stores;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Application.Dtos;
-using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.Uow;
@@ -150,23 +149,62 @@ namespace EasyAbp.EShop.Products.Products
}
decimal? min = null, max = null;
+ decimal? minWithoutDiscount = null, maxWithoutDiscount = null;
+
+ var discounts = new DiscountsInfoModel();
foreach (var productSku in product.ProductSkus)
{
+ var overrideProductDiscounts = false;
var priceDataModel = await _productManager.GetRealPriceAsync(product, productSku);
- if (min is null || priceDataModel.Price < min.Value)
+ if (min is null || priceDataModel.DiscountedPrice < min.Value)
+ {
+ min = priceDataModel.DiscountedPrice;
+ overrideProductDiscounts = true;
+ }
+
+ if (max is null || priceDataModel.DiscountedPrice > max.Value)
+ {
+ max = priceDataModel.DiscountedPrice;
+ }
+
+ if (minWithoutDiscount is null || priceDataModel.PriceWithoutDiscount < minWithoutDiscount.Value)
{
- min = productSku.Price;
+ minWithoutDiscount = priceDataModel.PriceWithoutDiscount;
+ }
+
+ if (maxWithoutDiscount is null || priceDataModel.PriceWithoutDiscount > maxWithoutDiscount.Value)
+ {
+ maxWithoutDiscount = priceDataModel.PriceWithoutDiscount;
+ }
+
+ foreach (var model in priceDataModel.ProductDiscounts)
+ {
+ var discount = discounts.FindProductDiscount(model.Name, model.Key);
+
+ if (discount is null || overrideProductDiscounts)
+ {
+ discounts.AddOrUpdateProductDiscount(new ProductDiscountInfoModel(model.Name, model.Key,
+ model.DisplayName, model.DiscountedAmount, model.FromTime, model.ToTime));
+ }
}
- if (max is null || priceDataModel.Price > max.Value)
+ foreach (var model in priceDataModel.OrderDiscountPreviews)
{
- max = productSku.Price;
+ var discount = discounts.FindOrderDiscount(model.Name, model.Key);
+
+ if (discount is null)
+ {
+ discounts.AddOrUpdateOrderDiscountPreview(new OrderDiscountPreviewInfoModel(model.Name,
+ model.Key, model.DisplayName, model.MinDiscountedAmount, model.MaxDiscountedAmount,
+ model.FromTime, model.ToTime));
+ }
}
}
- productView.SetPrices(min, max);
+ productView.SetPrices(min, max, minWithoutDiscount, maxWithoutDiscount);
+ productView.SetDiscounts(discounts);
}
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
index 0a19e6f6..ce85f7ff 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Application/EasyAbp/EShop/Products/ProductsApplicationAutoMapperProfile.cs
@@ -34,7 +34,6 @@ namespace EasyAbp.EShop.Products
CreateMap();
CreateMap()
.Ignore(dto => dto.Price)
- .Ignore(dto => dto.DiscountedPrice)
.Ignore(dto => dto.Inventory)
.Ignore(dto => dto.Sold);
CreateMap(MemberList.Source)
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
index 7d1cca8d..ddb8139d 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/en.json
@@ -98,6 +98,8 @@
"EasyAbp.EShop.Products:ProductAttributesModificationFailed": "Should ensure SKUs are empty if you want to modify attributes of a product.",
"EasyAbp.EShop.Products:StaticProductCannotBeModified": "Cannot modify the static product: {productId}",
"EasyAbp.EShop.Products:StoreIsNotProductOwner": "Store {storeId} is not a owner of the product {productId}",
- "EasyAbp.EShop.Products:InventoryInsufficient": "The inventory of the product {productId} (SKU: {productSkuId}) is insufficient, {quantity} are needed, but only {inventory}."
+ "EasyAbp.EShop.Products:InventoryInsufficient": "The inventory of the product {productId} (SKU: {productSkuId}) is insufficient, {quantity} are needed, but only {inventory}.",
+ "EasyAbp.EShop.Products:DiscountAmountOverflow": "The discount amount overflows.",
+ "EasyAbp.EShop.Products:InvalidTimePeriod": "Invalid time period."
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
index 4548d048..2f170274 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hans.json
@@ -95,6 +95,8 @@
"EasyAbp.EShop.Products:ProductAttributesModificationFailed": "请先确保Sku为空再修改商品的属性",
"EasyAbp.EShop.Products:StaticProductCannotBeModified": "不能修改静态商品{productId}",
"EasyAbp.EShop.Products:StoreIsNotProductOwner": "商店{storeId}不是商品{productId}的所有者 ",
- "EasyAbp.EShop.Products:InventoryInsufficient": "产品{productId} (SKU: {productSkuId})的库存不足,需要数量{quantity},但是只有数量{inventory}"
+ "EasyAbp.EShop.Products:InventoryInsufficient": "产品{productId} (SKU: {productSkuId})的库存不足,需要数量{quantity},但是只有数量{inventory}",
+ "EasyAbp.EShop.Products:DiscountAmountOverflow": "折扣金额溢出",
+ "EasyAbp.EShop.Products:InvalidTimePeriod": "不正确的时间区间"
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
index 6f94539f..8bed6416 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Localization/Products/zh-Hant.json
@@ -95,6 +95,8 @@
"EasyAbp.EShop.Products:ProductAttributesModificationFailed": "請先確保Sku為空再修改商品的屬性",
"EasyAbp.EShop.Products:StaticProductCannotBeModified": "不能修改靜態商品{productId}",
"EasyAbp.EShop.Products:StoreIsNotProductOwner": "商店{storeId}不是商品{productId}的所有者 ",
- "EasyAbp.EShop.Products:InventoryInsufficient": "產品{productId} (SKU: {productSkuId})的庫存不足,需要數量{quantity},但是只有數量{inventory}"
+ "EasyAbp.EShop.Products:InventoryInsufficient": "產品{productId} (SKU: {productSkuId})的庫存不足,需要數量{quantity},但是只有數量{inventory}",
+ "EasyAbp.EShop.Products:DiscountAmountOverflow": "折扣金額溢出",
+ "EasyAbp.EShop.Products:InvalidTimePeriod": "不正確的時間區間"
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountAmountOverflowException.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountAmountOverflowException.cs
new file mode 100644
index 00000000..fae95dc9
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountAmountOverflowException.cs
@@ -0,0 +1,10 @@
+using Volo.Abp;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public class DiscountAmountOverflowException : BusinessException
+{
+ public DiscountAmountOverflowException() : base(ProductsErrorCodes.DiscountAmountOverflow)
+ {
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountInfoModel.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountInfoModel.cs
new file mode 100644
index 00000000..97180c2a
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountInfoModel.cs
@@ -0,0 +1,45 @@
+using System;
+using JetBrains.Annotations;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public abstract class DiscountInfoModel
+{
+ [NotNull]
+ public string Name { get; set; }
+
+ [CanBeNull]
+ public string Key { get; set; }
+
+ [CanBeNull]
+ public string DisplayName { get; set; }
+
+ ///
+ /// When the discount begins to take effect.
+ ///
+ public DateTime? FromTime { get; set; }
+
+ ///
+ /// When the discount ends.
+ ///
+ public DateTime? ToTime { get; set; }
+
+ public DiscountInfoModel()
+ {
+ }
+
+ public DiscountInfoModel([NotNull] string name, [CanBeNull] string key, [CanBeNull] string displayName,
+ DateTime? fromTime, DateTime? toTime)
+ {
+ if (fromTime > toTime)
+ {
+ throw new InvalidTimePeriodException();
+ }
+
+ Name = name;
+ Key = key;
+ DisplayName = displayName;
+ FromTime = fromTime;
+ ToTime = toTime;
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountsInfoModel.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountsInfoModel.cs
new file mode 100644
index 00000000..d4457396
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/DiscountsInfoModel.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public class DiscountsInfoModel : IHasDiscountsInfo
+{
+ public List ProductDiscounts { get; set; }
+
+ public List OrderDiscountPreviews { get; set; }
+
+ public DiscountsInfoModel()
+ {
+ ProductDiscounts = new List();
+ OrderDiscountPreviews = new List();
+ }
+
+ public DiscountsInfoModel(List productDiscounts,
+ List orderDiscountPreviews)
+ {
+ ProductDiscounts = productDiscounts ?? new List();
+ OrderDiscountPreviews = orderDiscountPreviews ?? new List();
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/HasDiscountsInfoExtensions.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/HasDiscountsInfoExtensions.cs
new file mode 100644
index 00000000..dc96aa4c
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/HasDiscountsInfoExtensions.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using JetBrains.Annotations;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public static class HasDiscountsInfoExtensions
+{
+ public static decimal GetProductDiscountsDiscountedAmount(this IHasDiscountsInfo hasDiscountsInfo, DateTime now)
+ {
+ return hasDiscountsInfo.ProductDiscounts
+ .Where(x => !x.FromTime.HasValue || x.FromTime <= now)
+ .Where(x => !x.ToTime.HasValue || now <= x.ToTime)
+ .Sum(x => x.DiscountedAmount);
+ }
+
+ public static void AddOrUpdateProductDiscount(this IHasDiscountsInfo hasDiscountsInfo,
+ ProductDiscountInfoModel model)
+ {
+ var found = hasDiscountsInfo.FindProductDiscount(model.Name, model.Key);
+
+ if (found is null)
+ {
+ hasDiscountsInfo.ProductDiscounts.Add(model);
+ }
+ else
+ {
+ hasDiscountsInfo.ProductDiscounts.ReplaceOne(found, model);
+ }
+
+ hasDiscountsInfo.CheckDiscountedAmount();
+ }
+
+ public static ProductDiscountInfoModel FindProductDiscount(this IHasDiscountsInfo hasDiscountsInfo,
+ [NotNull] string name, [CanBeNull] string key)
+ {
+ return hasDiscountsInfo.ProductDiscounts.Find(x => x.Name == name && x.Key == key);
+ }
+
+ public static bool TryRemoveProductDiscount(this IHasDiscountsInfo hasDiscountsInfo, [NotNull] string name,
+ [CanBeNull] string key)
+ {
+ var found = hasDiscountsInfo.FindProductDiscount(name, key);
+
+ if (found is null)
+ {
+ return false;
+ }
+
+ hasDiscountsInfo.ProductDiscounts.Remove(found);
+
+ hasDiscountsInfo.CheckDiscountedAmount();
+
+ return true;
+ }
+
+ public static void AddOrUpdateOrderDiscountPreview(this IHasDiscountsInfo hasDiscountsInfo,
+ OrderDiscountPreviewInfoModel model)
+ {
+ var found = hasDiscountsInfo.FindOrderDiscount(model.Name, model.Key);
+
+ if (found is null)
+ {
+ hasDiscountsInfo.OrderDiscountPreviews.Add(model);
+ }
+ else
+ {
+ hasDiscountsInfo.OrderDiscountPreviews.ReplaceOne(found, model);
+ }
+
+ hasDiscountsInfo.CheckDiscountedAmount();
+ }
+
+ public static OrderDiscountPreviewInfoModel FindOrderDiscount(this IHasDiscountsInfo hasDiscountsInfo,
+ [NotNull] string name, [CanBeNull] string key)
+ {
+ return hasDiscountsInfo.OrderDiscountPreviews.Find(x => x.Name == name && x.Key == key);
+ }
+
+ public static bool TryRemoveOrderDiscountPreview(this IHasDiscountsInfo hasDiscountsInfo, [NotNull] string name,
+ [CanBeNull] string key)
+ {
+ var found = hasDiscountsInfo.FindOrderDiscount(name, key);
+
+ if (found is null)
+ {
+ return false;
+ }
+
+ hasDiscountsInfo.OrderDiscountPreviews.Remove(found);
+
+ hasDiscountsInfo.CheckDiscountedAmount();
+
+ return true;
+ }
+
+ private static void CheckDiscountedAmount(this IHasDiscountsInfo hasDiscountsInfo)
+ {
+ if (hasDiscountsInfo.ProductDiscounts.Any(x => x.DiscountedAmount < decimal.Zero) ||
+ hasDiscountsInfo.OrderDiscountPreviews.Any(x =>
+ x.MinDiscountedAmount < decimal.Zero || x.MaxDiscountedAmount < decimal.Zero ||
+ x.MinDiscountedAmount > x.MaxDiscountedAmount))
+ {
+ throw new DiscountAmountOverflowException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IHasDiscountsInfo.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IHasDiscountsInfo.cs
new file mode 100644
index 00000000..56c8af4d
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IHasDiscountsInfo.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public interface IHasDiscountsInfo
+{
+ ///
+ /// The Price of the ProductSku has been subtracted from these product discounts.
+ ///
+ List ProductDiscounts { get; }
+
+ ///
+ /// These order discount previews do not change the Price. They will be effective after placing an order.
+ ///
+ List OrderDiscountPreviews { get; }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IHasFullDiscountsInfo.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IHasFullDiscountsInfo.cs
new file mode 100644
index 00000000..44edfc55
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IHasFullDiscountsInfo.cs
@@ -0,0 +1,9 @@
+namespace EasyAbp.EShop.Products.Products;
+
+public interface IHasFullDiscountsInfo : IHasDiscountsInfo
+{
+ ///
+ /// The realtime price without subtracting the discount amount.
+ ///
+ decimal PriceWithoutDiscount { get; }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductSku.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductSku.cs
index c1d78ef7..df8df3f4 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductSku.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductSku.cs
@@ -14,8 +14,15 @@ namespace EasyAbp.EShop.Products.Products
[NotNull]
string Currency { get; }
+ ///
+ /// The official pricing value.
+ /// This property is only used for UI.
+ ///
decimal? OriginalPrice { get; }
+ ///
+ /// The realtime price.
+ ///
decimal Price { get; }
int OrderMinQuantity { get; }
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductView.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductView.cs
new file mode 100644
index 00000000..23e3866e
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/IProductView.cs
@@ -0,0 +1,14 @@
+namespace EasyAbp.EShop.Products.Products;
+
+public interface IProductView : IProductBase, IHasDiscountsInfo, IHasProductGroupDisplayName
+{
+ decimal? MinimumPrice { get; }
+
+ decimal? MaximumPrice { get; }
+
+ decimal? MinimumPriceWithoutDiscount { get; }
+
+ decimal? MaximumPriceWithoutDiscount { get; }
+
+ long Sold { get; }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/InvalidTimePeriodException.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/InvalidTimePeriodException.cs
new file mode 100644
index 00000000..5c9d2622
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/InvalidTimePeriodException.cs
@@ -0,0 +1,10 @@
+using Volo.Abp;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public class InvalidTimePeriodException : BusinessException
+{
+ public InvalidTimePeriodException() : base(ProductsErrorCodes.InvalidTimePeriod)
+ {
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/OrderDiscountPreviewInfoModel.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/OrderDiscountPreviewInfoModel.cs
new file mode 100644
index 00000000..99a45fae
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/OrderDiscountPreviewInfoModel.cs
@@ -0,0 +1,67 @@
+using System;
+using JetBrains.Annotations;
+
+namespace EasyAbp.EShop.Products.Products;
+
+[Serializable]
+public class OrderDiscountPreviewInfoModel : DiscountInfoModel, ICloneable
+{
+ public decimal MinDiscountedAmount { get; set; }
+
+ public decimal MaxDiscountedAmount { get; set; }
+
+ public OrderDiscountPreviewInfoModel()
+ {
+ }
+
+ public OrderDiscountPreviewInfoModel([NotNull] string name, [CanBeNull] string key, [CanBeNull] string displayName,
+ decimal minDiscountedAmount, decimal maxDiscountedAmount, DateTime? fromTime, DateTime? toTime) : base(name,
+ key, displayName, fromTime, toTime)
+ {
+ if (minDiscountedAmount < decimal.Zero || maxDiscountedAmount < decimal.Zero ||
+ minDiscountedAmount > maxDiscountedAmount)
+ {
+ throw new DiscountAmountOverflowException();
+ }
+
+ MinDiscountedAmount = minDiscountedAmount;
+ MaxDiscountedAmount = maxDiscountedAmount;
+ }
+
+ public object Clone()
+ {
+ return new OrderDiscountPreviewInfoModel(Name, Key, DisplayName, MinDiscountedAmount, MaxDiscountedAmount,
+ FromTime, ToTime);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is OrderDiscountPreviewInfoModel other && Equals(other);
+ }
+
+ protected bool Equals(OrderDiscountPreviewInfoModel other)
+ {
+ return Name == other.Name &&
+ Key == other.Key &&
+ DisplayName == other.DisplayName &&
+ MinDiscountedAmount == other.MinDiscountedAmount &&
+ MaxDiscountedAmount == other.MaxDiscountedAmount &&
+ Nullable.Equals(FromTime, other.FromTime) &&
+ Nullable.Equals(ToTime, other.ToTime);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = Name.GetHashCode();
+ hashCode = (hashCode * 397) ^ (Key != null ? Key.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (DisplayName != null ? DisplayName.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ MinDiscountedAmount.GetHashCode();
+ hashCode = (hashCode * 397) ^ MaxDiscountedAmount.GetHashCode();
+ hashCode = (hashCode * 397) ^ FromTime.GetHashCode();
+ hashCode = (hashCode * 397) ^ ToTime.GetHashCode();
+ return hashCode;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/ProductDiscountInfoModel.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/ProductDiscountInfoModel.cs
new file mode 100644
index 00000000..53ae0180
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/Products/ProductDiscountInfoModel.cs
@@ -0,0 +1,59 @@
+using System;
+using JetBrains.Annotations;
+
+namespace EasyAbp.EShop.Products.Products;
+
+[Serializable]
+public class ProductDiscountInfoModel : DiscountInfoModel, ICloneable
+{
+ public decimal DiscountedAmount { get; set; }
+
+ public ProductDiscountInfoModel()
+ {
+ }
+
+ public ProductDiscountInfoModel([NotNull] string name, [CanBeNull] string key, [CanBeNull] string displayName,
+ decimal discountedAmount, DateTime? fromTime, DateTime? toTime) : base(name, key, displayName, fromTime, toTime)
+ {
+ if (discountedAmount < decimal.Zero)
+ {
+ throw new DiscountAmountOverflowException();
+ }
+
+ DiscountedAmount = discountedAmount;
+ }
+
+ public object Clone()
+ {
+ return new ProductDiscountInfoModel(Name, Key, DisplayName, DiscountedAmount, FromTime, ToTime);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is ProductDiscountInfoModel other && Equals(other);
+ }
+
+ protected bool Equals(ProductDiscountInfoModel other)
+ {
+ return Name == other.Name &&
+ Key == other.Key &&
+ DisplayName == other.DisplayName &&
+ DiscountedAmount == other.DiscountedAmount &&
+ Nullable.Equals(FromTime, other.FromTime) &&
+ Nullable.Equals(ToTime, other.ToTime);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = Name.GetHashCode();
+ hashCode = (hashCode * 397) ^ (Key != null ? Key.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (DisplayName != null ? DisplayName.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ DiscountedAmount.GetHashCode();
+ hashCode = (hashCode * 397) ^ FromTime.GetHashCode();
+ hashCode = (hashCode * 397) ^ ToTime.GetHashCode();
+ return hashCode;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductsErrorCodes.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductsErrorCodes.cs
index 7f7baeca..71c0edea 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductsErrorCodes.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain.Shared/EasyAbp/EShop/Products/ProductsErrorCodes.cs
@@ -16,5 +16,7 @@
public const string StaticProductCannotBeModified = "EasyAbp.EShop.Products:StaticProductCannotBeModified";
public const string StoreIsNotProductOwner = "EasyAbp.EShop.Products:StoreIsNotProductOwner";
public const string InventoryInsufficient = "EasyAbp.EShop.Products:InventoryInsufficient";
+ public const string DiscountAmountOverflow = "EasyAbp.EShop.Products:DiscountAmountOverflow";
+ public const string InvalidTimePeriod = "EasyAbp.EShop.Products:InvalidTimePeriod";
}
}
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountProvider.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountProvider.cs
index 5e4b65c5..93f9bdef 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountProvider.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/IProductDiscountProvider.cs
@@ -1,10 +1,8 @@
-using System;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
-namespace EasyAbp.EShop.Products.Products
+namespace EasyAbp.EShop.Products.Products;
+
+public interface IProductDiscountProvider
{
- public interface IProductDiscountProvider
- {
- Task GetDiscountedPriceAsync(Product product, ProductSku productSku, decimal currentPrice);
- }
+ Task DiscountAsync(ProductDiscountContext context);
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/PriceDataModel.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/PriceDataModel.cs
index f8168434..7bd90669 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/PriceDataModel.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/PriceDataModel.cs
@@ -1,9 +1,37 @@
-namespace EasyAbp.EShop.Products.Products
+using System;
+using System.Collections.Generic;
+using Volo.Abp.Timing;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public class PriceDataModel : IHasFullDiscountsInfo
{
- public class PriceDataModel
+ public DateTime Now { get; }
+
+ public decimal PriceWithoutDiscount { get; }
+
+ ///
+ /// It's a sum of the amount of product discounts which in effect at the current time (this.).
+ ///
+ public decimal DiscountedAmount => this.GetProductDiscountsDiscountedAmount(Now);
+
+ ///
+ /// It has been subtracted from the product discounts which in effect at the current time (this.).
+ ///
+ public decimal DiscountedPrice => PriceWithoutDiscount - DiscountedAmount;
+
+ public List ProductDiscounts { get; } = new();
+
+ public List OrderDiscountPreviews { get; } = new();
+
+ public PriceDataModel(decimal priceWithoutDiscount, IClock clock)
{
- public decimal Price { get; set; }
-
- public decimal DiscountedPrice { get; set; }
+ if (PriceWithoutDiscount < decimal.Zero)
+ {
+ throw new OverflowException();
+ }
+
+ Now = clock.Now;
+ PriceWithoutDiscount = priceWithoutDiscount;
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductDiscountContext.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductDiscountContext.cs
new file mode 100644
index 00000000..7bec21bb
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductDiscountContext.cs
@@ -0,0 +1,19 @@
+using Volo.Abp.Timing;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public class ProductDiscountContext
+{
+ public Product Product { get; }
+
+ public ProductSku ProductSku { get; }
+
+ public PriceDataModel PriceDataModel { get; }
+
+ public ProductDiscountContext(Product product, ProductSku productSku, decimal priceFromPriceProvider, IClock clock)
+ {
+ Product = product;
+ ProductSku = productSku;
+ PriceDataModel = new PriceDataModel(priceFromPriceProvider, clock);
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs
index 4f3dbf36..f15eeb4c 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductManager.cs
@@ -272,19 +272,15 @@ namespace EasyAbp.EShop.Products.Products
{
var price = await _productPriceProvider.GetPriceAsync(product, productSku);
- var discountedPrice = price;
+ var context = new ProductDiscountContext(product, productSku, price, Clock);
// Todo: provider execution ordering.
foreach (var provider in LazyServiceProvider.LazyGetService>())
{
- discountedPrice = await provider.GetDiscountedPriceAsync(product, productSku, discountedPrice);
+ await provider.DiscountAsync(context);
}
- return new PriceDataModel
- {
- Price = price,
- DiscountedPrice = discountedPrice
- };
+ return context.PriceDataModel;
}
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductView.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductView.cs
index 37b7fd54..035392fe 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductView.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.Domain/EasyAbp/EShop/Products/Products/ProductView.cs
@@ -1,15 +1,15 @@
using System;
+using System.Collections.Generic;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace EasyAbp.EShop.Products.Products
{
- public class ProductView : CreationAuditedAggregateRoot,
- IProductBase, IHasProductGroupDisplayName, IMultiTenant
+ public class ProductView : CreationAuditedAggregateRoot, IProductView, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
- #region Properties of IProduct
+ #region Properties of IProductBase
public virtual Guid StoreId { get; protected set; }
@@ -43,10 +43,18 @@ namespace EasyAbp.EShop.Products.Products
public virtual string ProductGroupDisplayName { get; protected set; }
+ public virtual List ProductDiscounts { get; protected set; }
+
+ public virtual List OrderDiscountPreviews { get; protected set; }
+
public virtual decimal? MinimumPrice { get; protected set; }
public virtual decimal? MaximumPrice { get; protected set; }
+ public virtual decimal? MinimumPriceWithoutDiscount { get; protected set; }
+
+ public virtual decimal? MaximumPriceWithoutDiscount { get; protected set; }
+
public virtual long Sold { get; protected set; }
protected ProductView()
@@ -71,8 +79,12 @@ namespace EasyAbp.EShop.Products.Products
string mediaResources,
int displayOrder,
string productGroupDisplayName,
+ List productDiscounts,
+ List orderDiscountPreviews,
decimal? minimumPrice,
decimal? maximumPrice,
+ decimal? minimumPriceWithoutDiscount,
+ decimal? maximumPriceWithoutDiscount,
long sold
) : base(id)
{
@@ -93,8 +105,12 @@ namespace EasyAbp.EShop.Products.Products
DisplayOrder = displayOrder;
ProductGroupDisplayName = productGroupDisplayName;
+ ProductDiscounts = productDiscounts ?? new List();
+ OrderDiscountPreviews = orderDiscountPreviews ?? new List();
MinimumPrice = minimumPrice;
MaximumPrice = maximumPrice;
+ MinimumPriceWithoutDiscount = minimumPriceWithoutDiscount;
+ MaximumPriceWithoutDiscount = maximumPriceWithoutDiscount;
Sold = sold;
}
@@ -103,10 +119,18 @@ namespace EasyAbp.EShop.Products.Products
Sold = sold;
}
- public void SetPrices(decimal? minimumPrice, decimal? maximumPrice)
+ public void SetPrices(decimal? min, decimal? max, decimal? minWithoutDiscount, decimal? maxWithoutDiscount)
{
- MinimumPrice = minimumPrice;
- MaximumPrice = maximumPrice;
+ MinimumPrice = min;
+ MaximumPrice = max;
+ MinimumPriceWithoutDiscount = minWithoutDiscount;
+ MaximumPriceWithoutDiscount = maxWithoutDiscount;
+ }
+
+ public void SetDiscounts(IHasDiscountsInfo discountsInfo)
+ {
+ ProductDiscounts = discountsInfo.ProductDiscounts ?? new List();
+ OrderDiscountPreviews = discountsInfo.OrderDiscountPreviews ?? new List();
}
}
}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/EShopProductsEntityTypeBuilderExtensions.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/EShopProductsEntityTypeBuilderExtensions.cs
deleted file mode 100644
index 2f3dcf71..00000000
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/EShopProductsEntityTypeBuilderExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using EasyAbp.EShop.Products.EntityFrameworkCore.AttributeOptionIds;
-using EasyAbp.EShop.Products.Products;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Metadata.Builders;
-
-namespace EasyAbp.EShop.Products.EntityFrameworkCore;
-
-public static class EShopProductsEntityTypeBuilderExtensions
-{
- public static void TryConfigureAttributeOptionIds(this EntityTypeBuilder b)
- {
- if (b.Metadata.ClrType.IsAssignableTo())
- {
- b.Property(nameof(IHasAttributeOptionIds.AttributeOptionIds))
- .HasConversion()
- .Metadata.SetValueComparer(new AttributeOptionIdsValueComparer());
- }
- }
-}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs
index 68a6da95..593c613a 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContext.cs
@@ -1,8 +1,10 @@
+using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Categories;
+using EasyAbp.EShop.Products.EntityFrameworkCore.ValueMappings;
using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.ProductDetails;
using EasyAbp.EShop.Products.ProductHistories;
@@ -41,5 +43,15 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
builder.ConfigureEShopProducts();
}
+
+ protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
+ {
+ base.ConfigureConventions(configurationBuilder);
+
+ configurationBuilder.Properties>()
+ .HaveConversion();
+ configurationBuilder.Properties>()
+ .HaveConversion();
+ }
}
}
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs
index 58db971a..d0d2a208 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ProductsDbContextModelCreatingExtensions.cs
@@ -5,6 +5,7 @@ using EasyAbp.EShop.Products.ProductCategories;
using EasyAbp.EShop.Products.Categories;
using EasyAbp.EShop.Products.Products;
using System;
+using EasyAbp.EShop.Products.EntityFrameworkCore.ValueMappings;
using EasyAbp.EShop.Products.ProductDetails;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
@@ -133,7 +134,8 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
builder.Entity(b =>
{
b.ToTable(options.TablePrefix + "ProductViews", options.Schema);
- b.ConfigureByConvention();
+ b.ConfigureByConvention();
+ b.TryConfigureDiscountsInfo();
/* Configure more properties here */
@@ -141,6 +143,8 @@ namespace EasyAbp.EShop.Products.EntityFrameworkCore
b.Property(x => x.MinimumPrice).HasColumnType("decimal(20,8)");
b.Property(x => x.MaximumPrice).HasColumnType("decimal(20,8)");
+ b.Property(x => x.MinimumPriceWithoutDiscount).HasColumnType("decimal(20,8)");
+ b.Property(x => x.MaximumPriceWithoutDiscount).HasColumnType("decimal(20,8)");
});
}
}
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueComparer.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueComparer.cs
similarity index 85%
rename from modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueComparer.cs
rename to modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueComparer.cs
index 64aacd03..581c64e6 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueComparer.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueComparer.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore.ChangeTracking;
-namespace EasyAbp.EShop.Products.EntityFrameworkCore.AttributeOptionIds;
+namespace EasyAbp.EShop.Products.EntityFrameworkCore.ValueMappings;
public class AttributeOptionIdsValueComparer : ValueComparer>
{
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueConverter.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueConverter.cs
similarity index 85%
rename from modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueConverter.cs
rename to modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueConverter.cs
index 765b0869..8b279a5c 100644
--- a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueConverter.cs
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueConverter.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Text.Json;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-namespace EasyAbp.EShop.Products.EntityFrameworkCore.AttributeOptionIds;
+namespace EasyAbp.EShop.Products.EntityFrameworkCore.ValueMappings;
public class AttributeOptionIdsValueConverter : ValueConverter, string>
{
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/DiscountsInfoValueComparer.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/DiscountsInfoValueComparer.cs
new file mode 100644
index 00000000..9971331a
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/DiscountsInfoValueComparer.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using EasyAbp.EShop.Products.Products;
+using Microsoft.EntityFrameworkCore.ChangeTracking;
+
+namespace EasyAbp.EShop.Products.EntityFrameworkCore.ValueMappings;
+
+public class ProductDiscountsInfoValueComparer : ValueComparer>
+{
+ public ProductDiscountsInfoValueComparer()
+ : base(
+ (d1, d2) => d1.SequenceEqual(d2),
+ d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())),
+ d => d.Select(x => (ProductDiscountInfoModel)x.Clone()).ToList())
+ {
+ }
+}
+
+public class OrderDiscountPreviewsInfoValueComparer : ValueComparer>
+{
+ public OrderDiscountPreviewsInfoValueComparer()
+ : base(
+ (d1, d2) => d1.SequenceEqual(d2),
+ d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())),
+ d => new List(d))
+ {
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/DiscountsInfoValueConverter.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/DiscountsInfoValueConverter.cs
new file mode 100644
index 00000000..49d2812e
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/DiscountsInfoValueConverter.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using EasyAbp.EShop.Products.Products;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace EasyAbp.EShop.Products.EntityFrameworkCore.ValueMappings;
+
+public class ProductDiscountsInfoValueConverter : ValueConverter, string>
+{
+ public ProductDiscountsInfoValueConverter() : base(
+ v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
+ v => JsonSerializer.Deserialize>(v, (JsonSerializerOptions)null))
+ {
+ }
+}
+
+public class OrderDiscountPreviewsInfoValueConverter : ValueConverter, string>
+{
+ public OrderDiscountPreviewsInfoValueConverter() : base(
+ v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
+ v => JsonSerializer.Deserialize>(v, (JsonSerializerOptions)null))
+ {
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/EShopProductsEntityTypeBuilderExtensions.cs b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/EShopProductsEntityTypeBuilderExtensions.cs
new file mode 100644
index 00000000..c0fad94b
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/EShopProductsEntityTypeBuilderExtensions.cs
@@ -0,0 +1,31 @@
+using System;
+using EasyAbp.EShop.Products.Products;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace EasyAbp.EShop.Products.EntityFrameworkCore.ValueMappings;
+
+public static class EShopProductsEntityTypeBuilderExtensions
+{
+ public static void TryConfigureAttributeOptionIds(this EntityTypeBuilder b)
+ {
+ if (b.Metadata.ClrType.IsAssignableTo())
+ {
+ b.Property(nameof(IHasAttributeOptionIds.AttributeOptionIds))
+ .HasConversion()
+ .Metadata.SetValueComparer(new AttributeOptionIdsValueComparer());
+ }
+ }
+
+ public static void TryConfigureDiscountsInfo(this EntityTypeBuilder b)
+ {
+ if (b.Metadata.ClrType.IsAssignableTo())
+ {
+ b.Property(nameof(IHasDiscountsInfo.ProductDiscounts))
+ .HasConversion()
+ .Metadata.SetValueComparer(new ProductDiscountsInfoValueComparer());
+ b.Property(nameof(IHasDiscountsInfo.OrderDiscountPreviews))
+ .HasConversion()
+ .Metadata.SetValueComparer(new OrderDiscountPreviewsInfoValueComparer());
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/DemoProductDiscountProvider.cs b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/DemoProductDiscountProvider.cs
new file mode 100644
index 00000000..ab022954
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/DemoProductDiscountProvider.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Timing;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public class DemoProductDiscountProvider : IProductDiscountProvider
+{
+ private readonly IClock _clock;
+
+ public DemoProductDiscountProvider(IClock clock)
+ {
+ _clock = clock;
+ }
+
+ public Task DiscountAsync(ProductDiscountContext context)
+ {
+ if (context.Product.Id != ProductsTestData.Product1Id ||
+ context.ProductSku.Id != ProductsTestData.Product1Sku1Id)
+ {
+ return Task.CompletedTask;
+ }
+
+ context.PriceDataModel.ProductDiscounts.AddRange(new List
+ {
+ // These should affect:
+ new("DemoDiscount", "1", "Demo Discount 1", 0.01m, null, null),
+ new("DemoDiscount", "2", "Demo Discount 2", 0.01m, _clock.Now.AddDays(-1), null),
+ new("DemoDiscount", "3", "Demo Discount 3", 0.01m, null, _clock.Now.AddDays(1)),
+ new("DemoDiscount", "4", "Demo Discount 4", 0.01m, _clock.Now.AddDays(-1), _clock.Now.AddDays(1)),
+ // These should not affect: 0.01m,
+ new("DemoDiscount", "5", "Demo Discount 5", 0.01m, null, _clock.Now.AddDays(-1)),
+ new("DemoDiscount", "6", "Demo Discount 6", 0.01m, _clock.Now.AddDays(1), null),
+ new("DemoDiscount", "7", "Demo Discount 7", 0.01m, _clock.Now.AddDays(1), _clock.Now.AddDays(2)),
+ });
+
+ context.PriceDataModel.OrderDiscountPreviews.AddRange(new List
+ {
+ new("DemoDiscount", "1", "Demo Discount 1", 0.01m, 0.01m, null, null),
+ new("DemoDiscount", "2", "Demo Discount 2", 0.01m, 0.01m, _clock.Now.AddDays(-1), _clock.Now.AddDays(1)),
+ });
+
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductDiscountTests.cs b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductDiscountTests.cs
new file mode 100644
index 00000000..46c61936
--- /dev/null
+++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductDiscountTests.cs
@@ -0,0 +1,43 @@
+using System.Threading.Tasks;
+using EasyAbp.EShop.Products.Products.Dtos;
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace EasyAbp.EShop.Products.Products;
+
+public class ProductDiscountTests : ProductsApplicationTestBase
+{
+ protected override void AfterAddApplication(IServiceCollection services)
+ {
+ services.AddTransient();
+ base.AfterAddApplication(services);
+ }
+
+ [Fact]
+ public async Task Should_Get_Product_With_Discount()
+ {
+ var productAppService = GetRequiredService();
+
+ var product1 = await productAppService.GetAsync(ProductsTestData.Product1Id);
+ var sku1 = (ProductSkuDto)product1.GetSkuById(ProductsTestData.Product1Sku1Id);
+ var sku2 = (ProductSkuDto)product1.GetSkuById(ProductsTestData.Product1Sku2Id);
+
+ sku1.Price.ShouldBe(1m - 0.01m * 4);
+ sku1.ProductDiscounts.Count.ShouldBe(7);
+ sku1.ProductDiscounts.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "1");
+ sku1.ProductDiscounts.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "2");
+ sku1.ProductDiscounts.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "3");
+ sku1.ProductDiscounts.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "4");
+ sku1.ProductDiscounts.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "5");
+ sku1.ProductDiscounts.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "6");
+ sku1.ProductDiscounts.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "7");
+ sku1.OrderDiscountPreviews.Count.ShouldBe(2);
+ sku1.OrderDiscountPreviews.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "1");
+ sku1.OrderDiscountPreviews.ShouldContain(x => x.Name == "DemoDiscount" && x.Key == "2");
+
+ sku2.Price.ShouldBe(2m);
+ sku2.ProductDiscounts.ShouldBeEmpty();
+ sku2.OrderDiscountPreviews.ShouldBeEmpty();
+ }
+}
\ No newline at end of file
diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductViewAppServiceTests.cs b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductViewAppServiceTests.cs
index d631bf1e..1307721b 100644
--- a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductViewAppServiceTests.cs
+++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.Application.Tests/Products/ProductViewAppServiceTests.cs
@@ -31,14 +31,14 @@ namespace EasyAbp.EShop.Products.Products
var productDto = getListResult.Items.FirstOrDefault(x => x.Id == ProductsTestData.Product1Id);
productDto.ShouldNotBeNull();
- productDto.MinimumPrice.ShouldBe(1m);
- productDto.MaximumPrice.ShouldBe(3m);
+ productDto.MinimumPriceWithoutDiscount.ShouldBe(1m);
+ productDto.MaximumPriceWithoutDiscount.ShouldBe(3m);
var getResult = await _productViewAppService.GetAsync(ProductsTestData.Product1Id);
getResult.ShouldNotBeNull();
- getResult.MinimumPrice.ShouldBe(1m);
- getResult.MaximumPrice.ShouldBe(3m);
+ getResult.MinimumPriceWithoutDiscount.ShouldBe(1m);
+ getResult.MaximumPriceWithoutDiscount.ShouldBe(3m);
}
diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EasyAbp.EShop.Products.EntityFrameworkCore.Tests.csproj b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EasyAbp.EShop.Products.EntityFrameworkCore.Tests.csproj
index 84d97499..a96a0410 100644
--- a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EasyAbp.EShop.Products.EntityFrameworkCore.Tests.csproj
+++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EasyAbp.EShop.Products.EntityFrameworkCore.Tests.csproj
@@ -7,11 +7,10 @@
-
-
+
diff --git a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopProductsEntityFrameworkCoreTestModule.cs b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopProductsEntityFrameworkCoreTestModule.cs
index 6ad07173..d81be9fe 100644
--- a/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopProductsEntityFrameworkCoreTestModule.cs
+++ b/modules/EasyAbp.EShop.Products/test/EasyAbp.EShop.Products.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopProductsEntityFrameworkCoreTestModule.cs
@@ -3,14 +3,16 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.Modularity;
namespace EasyAbp.EShop.Products.EntityFrameworkCore
{
[DependsOn(
typeof(ProductsTestBaseModule),
- typeof(EShopProductsEntityFrameworkCoreModule)
- )]
+ typeof(EShopProductsEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCoreSqliteModule)
+ )]
public class EShopProductsEntityFrameworkCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests.csproj b/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests.csproj
index b1a8f66f..7b1f5765 100644
--- a/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests.csproj
+++ b/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests.csproj
@@ -7,11 +7,10 @@
-
-
+
diff --git a/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopStoresEntityFrameworkCoreTestModule.cs b/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopStoresEntityFrameworkCoreTestModule.cs
index 704f185b..fb6a879b 100644
--- a/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopStoresEntityFrameworkCoreTestModule.cs
+++ b/modules/EasyAbp.EShop.Stores/test/EasyAbp.EShop.Stores.EntityFrameworkCore.Tests/EntityFrameworkCore/EShopStoresEntityFrameworkCoreTestModule.cs
@@ -3,14 +3,16 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.Modularity;
namespace EasyAbp.EShop.Stores.EntityFrameworkCore
{
[DependsOn(
typeof(EShopStoresTestBaseModule),
- typeof(EShopStoresEntityFrameworkCoreModule)
- )]
+ typeof(EShopStoresEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCoreSqliteModule)
+ )]
public class EShopStoresEntityFrameworkCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/BasketItemDto.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/BasketItemDto.cs
index 45d44aa0..6314bb23 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/BasketItemDto.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/BasketItemDto.cs
@@ -1,15 +1,17 @@
using System;
+using System.Collections.Generic;
+using EasyAbp.EShop.Products.Products;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos
{
[Serializable]
- public class BasketItemDto : ExtensibleAuditedEntityDto
+ public class BasketItemDto : ExtensibleAuditedEntityDto, IServerSideBasketItemInfo
{
public string BasketName { get; set; }
public Guid UserId { get; set; }
-
+
public Guid StoreId { get; set; }
public Guid ProductId { get; set; }
@@ -18,26 +20,28 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos
public int Quantity { get; set; }
+ public decimal PriceWithoutDiscount { get; set; }
+
+ public decimal TotalPriceWithoutDiscount { get; set; }
+
public string MediaResources { get; set; }
public string ProductUniqueName { get; set; }
-
+
public string ProductDisplayName { get; set; }
public string SkuName { get; set; }
-
+
public string SkuDescription { get; set; }
public string Currency { get; set; }
- public decimal UnitPrice { get; set; }
-
- public decimal TotalPrice { get; set; }
-
- public decimal TotalDiscount { get; set; }
-
public int Inventory { get; set; }
-
+
public bool IsInvalid { get; set; }
+
+ public List ProductDiscounts { get; set; }
+
+ public List OrderDiscountPreviews { get; set; }
}
}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs
index 2256d63e..7b8bc1a6 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using EasyAbp.EShop.Products.Products;
using JetBrains.Annotations;
using Volo.Abp.ObjectExtending;
@@ -8,71 +10,80 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos;
public class ClientSideBasketItemModel : ExtensibleObject, IBasketItem
{
public Guid Id { get; set; }
-
+
public string BasketName { get; set; }
-
+
public int Quantity { get; set; }
public Guid StoreId { get; set; }
-
+
public Guid ProductId { get; set; }
-
+
public string ProductUniqueName { get; set; }
-
+
public string ProductDisplayName { get; set; }
-
+
public Guid ProductSkuId { get; set; }
-
+
public string SkuName { get; set; }
-
+
public string SkuDescription { get; set; }
-
+
public string MediaResources { get; set; }
public string Currency { get; set; }
-
- public decimal UnitPrice { get; set; }
-
- public decimal TotalPrice { get; set; }
-
- public decimal TotalDiscount { get; set; }
-
+
+ public decimal PriceWithoutDiscount { get; set; }
+
+ public decimal TotalPriceWithoutDiscount { get; set; }
+
+ public List ProductDiscounts { get; set; }
+
+ public List OrderDiscountPreviews { get; set; }
+
public int Inventory { get; set; }
-
+
public bool IsInvalid { get; set; }
+ public ClientSideBasketItemModel()
+ {
+ }
+
public ClientSideBasketItemModel(
Guid id,
[NotNull] string basketName,
Guid storeId,
Guid productId,
- Guid productSkuId)
+ Guid productSkuId,
+ List productDiscounts,
+ List orderDiscountPreviews)
{
Id = id;
BasketName = basketName;
StoreId = storeId;
ProductId = productId;
ProductSkuId = productSkuId;
+ ProductDiscounts = productDiscounts ?? new List();
+ OrderDiscountPreviews = orderDiscountPreviews ?? new List();
}
-
+
public void SetIsInvalid(bool isInvalid)
{
IsInvalid = isInvalid;
}
- public void UpdateProductData(int quantity, IProductData productData)
+ public void Update(int quantity, IProductData productData)
{
Quantity = quantity;
-
+
MediaResources = productData.MediaResources;
ProductUniqueName = productData.ProductUniqueName;
ProductDisplayName = productData.ProductDisplayName;
SkuName = productData.SkuName;
SkuDescription = productData.SkuDescription;
Currency = productData.Currency;
- UnitPrice = productData.UnitPrice;
- TotalPrice = productData.TotalPrice;
- TotalDiscount = productData.TotalDiscount;
+ PriceWithoutDiscount = productData.PriceWithoutDiscount;
+ TotalPriceWithoutDiscount = productData.PriceWithoutDiscount * quantity;
Inventory = productData.Inventory;
}
}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs
index 9563b2b1..39034892 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs
@@ -1,25 +1,28 @@
-namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
+using System.Collections.Generic;
+using EasyAbp.EShop.Products.Products;
+
+namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
{
public class ProductDataModel : IProductData
{
public string MediaResources { get; set; }
-
+
public string ProductUniqueName { get; set; }
-
+
public string ProductDisplayName { get; set; }
-
+
public string SkuName { get; set; }
-
+
public string SkuDescription { get; set; }
-
+
public string Currency { get; set; }
-
- public decimal UnitPrice { get; set; }
-
- public decimal TotalPrice { get; set; }
-
- public decimal TotalDiscount { get; set; }
-
+
+ public decimal PriceWithoutDiscount { get; set; }
+
+ public List ProductDiscounts { get; set; } = new();
+
+ public List OrderDiscountPreviews { get; set; } = new();
+
public int Inventory { get; set; }
}
}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs
index 7b257ac0..ff904e1a 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos;
@@ -35,7 +37,7 @@ public class BasicBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater,
return;
}
- item.UpdateProductData(targetQuantity, new ProductDataModel
+ item.Update(targetQuantity, new ProductDataModel
{
MediaResources = productSkuDto.MediaResources ?? productDto.MediaResources,
ProductUniqueName = productDto.UniqueName,
@@ -43,9 +45,9 @@ public class BasicBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater,
SkuName = productSkuDto.Name,
SkuDescription = await ProductSkuDescriptionProvider.GenerateAsync(productDto, productSkuDto),
Currency = productSkuDto.Currency,
- UnitPrice = productSkuDto.DiscountedPrice,
- TotalPrice = productSkuDto.DiscountedPrice * item.Quantity,
- TotalDiscount = (productSkuDto.Price - productSkuDto.DiscountedPrice) * item.Quantity,
+ PriceWithoutDiscount = productSkuDto.PriceWithoutDiscount,
+ ProductDiscounts = productSkuDto.ProductDiscounts,
+ OrderDiscountPreviews = productSkuDto.OrderDiscountPreviews,
Inventory = productSkuDto.Inventory
});
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs
index f58bbea8..9bcb3eb9 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs
@@ -179,7 +179,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
return await MapToGetOutputDtoAsync(item);
}
- var productSkuDto = productDto.FindSkuById(input.ProductSkuId);
+ var productSkuDto = (ProductSkuDto)productDto.FindSkuById(input.ProductSkuId);
if (productSkuDto == null)
{
@@ -187,8 +187,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
}
item = new BasketItem(GuidGenerator.Create(), CurrentTenant.Id, input.BasketName, CurrentUser.GetId(),
- productDto.StoreId, input.ProductId, input.ProductSkuId);
-
+ productDto.StoreId, input.ProductId, input.ProductSkuId, productSkuDto.ProductDiscounts,
+ productSkuDto.OrderDiscountPreviews);
+
input.MapExtraPropertiesTo(item);
await UpdateProductDataAsync(input.Quantity, item, productDto);
@@ -269,7 +270,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
var productDto = products[dto.ProductId];
- var productSkuDto = productDto.FindSkuById(dto.ProductSkuId);
+ var productSkuDto = (ProductSkuDto)productDto.FindSkuById(dto.ProductSkuId);
if (productSkuDto == null)
{
@@ -278,8 +279,8 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
var id = dto.Id ?? GuidGenerator.Create();
- var item = new ClientSideBasketItemModel(id, dto.BasketName, productDto.StoreId,
- dto.ProductId, dto.ProductSkuId);
+ var item = new ClientSideBasketItemModel(id, dto.BasketName, productDto.StoreId, dto.ProductId,
+ dto.ProductSkuId, productSkuDto.ProductDiscounts, productSkuDto.OrderDiscountPreviews);
await UpdateProductDataAsync(dto.Quantity, item, productDto);
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp.EShop.Plugins.Baskets.Domain.Shared.csproj b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp.EShop.Plugins.Baskets.Domain.Shared.csproj
index ce693f30..07beb6d1 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp.EShop.Plugins.Baskets.Domain.Shared.csproj
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp.EShop.Plugins.Baskets.Domain.Shared.csproj
@@ -20,5 +20,9 @@
+
+
+
+
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs
index 15d13d5a..6b32199b 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs
@@ -1,27 +1,8 @@
-using System;
-using JetBrains.Annotations;
-using Volo.Abp.Data;
-
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems;
-public interface IBasketItem : IProductData, IHasExtraProperties
+public interface IBasketItem : IBasketItemInfo
{
- Guid Id { get; }
-
- [NotNull]
- string BasketName { get; }
-
- Guid StoreId { get; }
-
- Guid ProductId { get; }
-
- Guid ProductSkuId { get; }
-
- int Quantity { get; }
-
- bool IsInvalid { get; }
-
void SetIsInvalid(bool isInvalid);
- void UpdateProductData(int quantity, IProductData productData);
+ void Update(int quantity, IProductData productData);
}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemInfo.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemInfo.cs
new file mode 100644
index 00000000..4922b72f
--- /dev/null
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemInfo.cs
@@ -0,0 +1,28 @@
+using System;
+using JetBrains.Annotations;
+using Volo.Abp.Data;
+
+namespace EasyAbp.EShop.Plugins.Baskets.BasketItems;
+
+public interface IBasketItemInfo : IProductData, IHasExtraProperties
+{
+ Guid Id { get; }
+
+ [NotNull]
+ string BasketName { get; }
+
+ Guid StoreId { get; }
+
+ Guid ProductId { get; }
+
+ Guid ProductSkuId { get; }
+
+ int Quantity { get; }
+
+ ///
+ /// PriceWithoutDiscount * Quantity
+ ///
+ decimal TotalPriceWithoutDiscount { get; }
+
+ bool IsInvalid { get; }
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs
index 6692462e..367160f0 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs
@@ -1,25 +1,21 @@
-namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
+using EasyAbp.EShop.Products.Products;
+
+namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
{
- public interface IProductData
+ public interface IProductData : IHasFullDiscountsInfo
{
string MediaResources { get; }
-
+
string ProductUniqueName { get; }
-
+
string ProductDisplayName { get; }
-
+
string SkuName { get; }
-
+
string SkuDescription { get; }
string Currency { get; }
-
- decimal UnitPrice { get; }
-
- decimal TotalPrice { get; }
-
- decimal TotalDiscount { get; }
-
+
int Inventory { get; }
}
}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IServerSideBasketItemInfo.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IServerSideBasketItemInfo.cs
new file mode 100644
index 00000000..d1d67048
--- /dev/null
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IServerSideBasketItemInfo.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace EasyAbp.EShop.Plugins.Baskets.BasketItems;
+
+public interface IServerSideBasketItemInfo : IBasketItemInfo
+{
+ Guid UserId { get; }
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/EShopPluginsBasketsDomainSharedModule.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/EShopPluginsBasketsDomainSharedModule.cs
index 2031e0ca..6cc857e7 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/EShopPluginsBasketsDomainSharedModule.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/EShopPluginsBasketsDomainSharedModule.cs
@@ -1,6 +1,7 @@
using Volo.Abp.Modularity;
using Volo.Abp.Localization;
using EasyAbp.EShop.Plugins.Baskets.Localization;
+using EasyAbp.EShop.Products;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Validation;
using Volo.Abp.Validation.Localization;
@@ -9,7 +10,8 @@ using Volo.Abp.VirtualFileSystem;
namespace EasyAbp.EShop.Plugins.Baskets
{
[DependsOn(
- typeof(AbpValidationModule)
+ typeof(AbpValidationModule),
+ typeof(EShopProductsDomainSharedModule)
)]
public class EShopPluginsBasketsDomainSharedModule : AbpModule
{
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json
index ba85b081..1ab1f79a 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json
@@ -12,17 +12,18 @@
"BasketItemProductId": "Product ID",
"BasketItemProductSkuId": "Product SKU ID",
"BasketItemQuantity": "Quantity",
+ "PriceWithoutDiscount": "Price without discount",
+ "TotalPriceWithoutDiscount": "Total price without discount",
"BasketItemMediaResources": "Media resources",
"BasketItemProductUniqueName": "Product unique name",
"BasketItemProductDisplayName": "Product display name",
"BasketItemSkuName": "SKU name",
"BasketItemSkuDescription": "SKU description",
"BasketItemCurrency": "Currency",
- "BasketItemUnitPrice": "Unit price",
- "BasketItemTotalPrice": "Total price",
- "BasketItemTotalDiscount": "Total discount",
"BasketItemInventory": "Inventory",
"BasketItemIsInvalid": "Invalid",
+ "ProductDiscounts": "Product discounts",
+ "OrderDiscountPreviews": "Order discount previews",
"CreateBasketItem": "New",
"EditBasketItem": "Edit",
"BasketItemDeletionConfirmationMessage": "Are you sure to delete the basket item {0}?",
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json
index 9d917b82..d33b0a16 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json
@@ -12,17 +12,18 @@
"BasketItemProductId": "商品 ID",
"BasketItemProductSkuId": "商品 SKU ID",
"BasketItemQuantity": "数量",
+ "PriceWithoutDiscount": "单价(不含折扣)",
+ "TotalPriceWithoutDiscount": "总价(不含折扣)",
"BasketItemMediaResources": "多媒体资源",
"BasketItemProductUniqueName": "商品编号",
"BasketItemProductDisplayName": "商品名称",
"BasketItemSkuName": "SKU 编号",
"BasketItemSkuDescription": "SKU 描述",
"BasketItemCurrency": "币种",
- "BasketItemUnitPrice": "单价",
- "BasketItemTotalPrice": "总价",
- "BasketItemTotalDiscount": "总折扣",
"BasketItemInventory": "库存数",
"BasketItemIsInvalid": "是否不可用",
+ "ProductDiscounts": "商品折扣",
+ "OrderDiscountPreviews": "订单折扣(预览)",
"CreateBasketItem": "新建",
"EditBasketItem": "编辑",
"BasketItemDeletionConfirmationMessage": "确认删除购物车项 {0}?",
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json
index 20e509a7..9e9d31ca 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json
@@ -12,17 +12,18 @@
"BasketItemProductId": "商品 ID",
"BasketItemProductSkuId": "商品 SKU ID",
"BasketItemQuantity": "數量",
+ "PriceWithoutDiscount": "單價(不含折扣)",
+ "TotalPriceWithoutDiscount": "總價(不含折扣)",
"BasketItemMediaResources": "多媒體資源",
"BasketItemProductUniqueName": "商品編號",
"BasketItemProductDisplayName": "商品名稱",
"BasketItemSkuName": "SKU 編號",
"BasketItemSkuDescription": "SKU 描述",
"BasketItemCurrency": "幣種",
- "BasketItemUnitPrice": "單價",
- "BasketItemTotalPrice": "總價",
- "BasketItemTotalDiscount": "總折扣",
"BasketItemInventory": "庫存數",
"BasketItemIsInvalid": "是否不可用",
+ "ProductDiscounts": "商品折扣",
+ "OrderDiscountPreviews": "訂單折扣(預覽)",
"CreateBasketItem": "新建",
"EditBasketItem": "編輯",
"BasketItemDeletionConfirmationMessage": "確認刪除購物車項 {0}?",
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs
index 4b567d7f..64c08444 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs
@@ -1,32 +1,38 @@
using System;
+using System.Collections.Generic;
+using EasyAbp.EShop.Products.Products;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
{
- public class BasketItem : AuditedAggregateRoot, IBasketItem, IMultiTenant
+ public class BasketItem : AuditedAggregateRoot, IBasketItem, IServerSideBasketItemInfo, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
-
+
public virtual string BasketName { get; protected set; }
-
+
public virtual Guid UserId { get; protected set; }
-
+
public virtual Guid StoreId { get; protected set; }
-
+
public virtual Guid ProductId { get; protected set; }
-
+
public virtual Guid ProductSkuId { get; protected set; }
-
+
public virtual int Quantity { get; protected set; }
-
+
+ public virtual decimal PriceWithoutDiscount { get; protected set; }
+
+ public virtual decimal TotalPriceWithoutDiscount { get; protected set; }
+
[CanBeNull]
public virtual string MediaResources { get; protected set; }
-
+
[CanBeNull]
public virtual string ProductUniqueName { get; protected set; }
-
+
[NotNull]
public virtual string ProductDisplayName { get; protected set; }
@@ -38,21 +44,19 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
[NotNull]
public virtual string Currency { get; protected set; }
-
- public virtual decimal UnitPrice { get; protected set; }
-
- public virtual decimal TotalPrice { get; protected set; }
-
- public virtual decimal TotalDiscount { get; protected set; }
-
+
public virtual int Inventory { get; protected set; }
-
+
public virtual bool IsInvalid { get; protected set; }
+ public virtual List ProductDiscounts { get; protected set; }
+
+ public virtual List OrderDiscountPreviews { get; protected set; }
+
protected BasketItem()
{
}
-
+
public BasketItem(
Guid id,
Guid? tenantId,
@@ -60,7 +64,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
Guid userId,
Guid storeId,
Guid productId,
- Guid productSkuId) : base(id)
+ Guid productSkuId,
+ List productDiscounts,
+ List orderDiscountPreviews) : base(id)
{
TenantId = tenantId;
BasketName = basketName;
@@ -68,21 +74,22 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
StoreId = storeId;
ProductId = productId;
ProductSkuId = productSkuId;
+ ProductDiscounts = productDiscounts ?? new List();
+ OrderDiscountPreviews = orderDiscountPreviews ?? new List();
}
- public void UpdateProductData(int quantity, IProductData productData)
+ public void Update(int quantity, IProductData productData)
{
Quantity = quantity;
-
+
MediaResources = productData.MediaResources;
ProductUniqueName = productData.ProductUniqueName;
ProductDisplayName = productData.ProductDisplayName;
SkuName = productData.SkuName;
SkuDescription = productData.SkuDescription;
Currency = productData.Currency;
- UnitPrice = productData.UnitPrice;
- TotalPrice = productData.TotalPrice;
- TotalDiscount = productData.TotalDiscount;
+ PriceWithoutDiscount = productData.PriceWithoutDiscount;
+ TotalPriceWithoutDiscount = productData.PriceWithoutDiscount * quantity;
Inventory = productData.Inventory;
}
@@ -91,4 +98,4 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
IsInvalid = isInvalid;
}
}
-}
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/ProductUpdateRecorder.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/ProductUpdateRecorder.cs
index c8d577f3..c07dc9bd 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/ProductUpdateRecorder.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/ProductUpdateRecorder.cs
@@ -16,6 +16,8 @@ namespace EasyAbp.EShop.Plugins.Baskets.ProductUpdates
IProductUpdateRecorder,
IDistributedEventHandler>,
IDistributedEventHandler,
+ // todo: while discount changed
+ // todo: manually refresh event
ITransientDependency
{
private readonly IGuidGenerator _guidGenerator;
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContext.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContext.cs
index e16f2ff1..c84889c6 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContext.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContext.cs
@@ -1,8 +1,11 @@
+using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using EasyAbp.EShop.Plugins.Baskets.BasketItems;
+using EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore.ValueMappings;
using EasyAbp.EShop.Plugins.Baskets.ProductUpdates;
+using EasyAbp.EShop.Products.Products;
namespace EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore
{
@@ -15,10 +18,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore
public DbSet BasketItems { get; set; }
public DbSet ProductUpdates { get; set; }
- public BasketsDbContext(DbContextOptions options)
+ public BasketsDbContext(DbContextOptions options)
: base(options)
{
-
}
protected override void OnModelCreating(ModelBuilder builder)
@@ -27,5 +29,15 @@ namespace EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore
builder.ConfigureEShopPluginsBaskets();
}
+
+ protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
+ {
+ base.ConfigureConventions(configurationBuilder);
+
+ configurationBuilder.Properties>()
+ .HaveConversion();
+ configurationBuilder.Properties>()
+ .HaveConversion();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContextModelCreatingExtensions.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContextModelCreatingExtensions.cs
index b30a1b00..9c68a46f 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContextModelCreatingExtensions.cs
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/BasketsDbContextModelCreatingExtensions.cs
@@ -1,6 +1,8 @@
using EasyAbp.EShop.Plugins.Baskets.BasketItems;
using System;
+using EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore.ValueMappings;
using EasyAbp.EShop.Plugins.Baskets.ProductUpdates;
+using EasyAbp.EShop.Products.Products;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
@@ -46,26 +48,26 @@ namespace EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore
builder.Entity(b =>
{
b.ToTable(options.TablePrefix + "BasketItems", options.Schema);
- b.ConfigureByConvention();
+ b.ConfigureByConvention();
+ b.TryConfigureDiscountsInfo();
/* Configure more properties here */
b.HasIndex(x => x.UserId);
- b.Property(x => x.UnitPrice).HasColumnType("decimal(20,8)");
- b.Property(x => x.TotalPrice).HasColumnType("decimal(20,8)");
- b.Property(x => x.TotalDiscount).HasColumnType("decimal(20,8)");
+ b.Property(x => x.PriceWithoutDiscount).HasColumnType("decimal(20,8)");
+ b.Property(x => x.TotalPriceWithoutDiscount).HasColumnType("decimal(20,8)");
});
builder.Entity(b =>
{
b.ToTable(options.TablePrefix + "ProductUpdates", options.Schema);
- b.ConfigureByConvention();
-
+ b.ConfigureByConvention();
+
/* Configure more properties here */
b.HasIndex(x => x.ProductSkuId);
});
}
}
-}
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/DiscountsInfoValueComparer.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/DiscountsInfoValueComparer.cs
new file mode 100644
index 00000000..dbf5504a
--- /dev/null
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/DiscountsInfoValueComparer.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using EasyAbp.EShop.Products.Products;
+using Microsoft.EntityFrameworkCore.ChangeTracking;
+
+namespace EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore.ValueMappings;
+
+public class ProductDiscountsInfoValueComparer : ValueComparer>
+{
+ public ProductDiscountsInfoValueComparer()
+ : base(
+ (d1, d2) => d1.SequenceEqual(d2),
+ d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())),
+ d => d.Select(x => (ProductDiscountInfoModel)x.Clone()).ToList())
+ {
+ }
+}
+
+public class OrderDiscountPreviewsInfoValueComparer : ValueComparer>
+{
+ public OrderDiscountPreviewsInfoValueComparer()
+ : base(
+ (d1, d2) => d1.SequenceEqual(d2),
+ d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())),
+ d => new List(d))
+ {
+ }
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/DiscountsInfoValueConverter.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/DiscountsInfoValueConverter.cs
new file mode 100644
index 00000000..b9a7a2fe
--- /dev/null
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/DiscountsInfoValueConverter.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using EasyAbp.EShop.Products.Products;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore.ValueMappings;
+
+public class ProductDiscountsInfoValueConverter : ValueConverter, string>
+{
+ public ProductDiscountsInfoValueConverter() : base(
+ v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
+ v => JsonSerializer.Deserialize>(v, (JsonSerializerOptions)null))
+ {
+ }
+}
+
+public class OrderDiscountPreviewsInfoValueConverter : ValueConverter, string>
+{
+ public OrderDiscountPreviewsInfoValueConverter() : base(
+ v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
+ v => JsonSerializer.Deserialize>(v, (JsonSerializerOptions)null))
+ {
+ }
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/EShopProductsEntityTypeBuilderExtensions.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/EShopProductsEntityTypeBuilderExtensions.cs
new file mode 100644
index 00000000..1c8fa77e
--- /dev/null
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore/EasyAbp/EShop/Plugins/Baskets/EntityFrameworkCore/ValueMappings/EShopProductsEntityTypeBuilderExtensions.cs
@@ -0,0 +1,21 @@
+using System;
+using EasyAbp.EShop.Products.Products;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore.ValueMappings;
+
+public static class EShopProductsEntityTypeBuilderExtensions
+{
+ public static void TryConfigureDiscountsInfo(this EntityTypeBuilder b)
+ {
+ if (b.Metadata.ClrType.IsAssignableTo())
+ {
+ b.Property(nameof(IHasDiscountsInfo.ProductDiscounts))
+ .HasConversion()
+ .Metadata.SetValueComparer(new ProductDiscountsInfoValueComparer());
+ b.Property(nameof(IHasDiscountsInfo.OrderDiscountPreviews))
+ .HasConversion()
+ .Metadata.SetValueComparer(new OrderDiscountPreviewsInfoValueComparer());
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml
index 69247564..e2b8faa2 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml
@@ -54,15 +54,14 @@
| @L["BasketItemProductId"] |
@L["BasketItemProductSkuId"] |
@L["BasketItemQuantity"] |
+ @L["PriceWithoutDiscount"] |
+ @L["TotalPriceWithoutDiscount"] |
@L["BasketItemMediaResources"] |
@L["BasketItemProductUniqueName"] |
@L["BasketItemProductDisplayName"] |
@L["BasketItemSkuName"] |
@L["BasketItemSkuDescription"] |
@L["BasketItemCurrency"] |
- @L["BasketItemUnitPrice"] |
- @L["BasketItemTotalPrice"] |
- @L["BasketItemTotalDiscount"] |
@L["BasketItemInventory"] |
@L["BasketItemIsInvalid"] |
diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js
index 950d55d2..6767b039 100644
--- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js
+++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js
@@ -57,15 +57,14 @@ $(function () {
{ data: "productId" },
{ data: "productSkuId" },
{ data: "quantity" },
+ { data: "priceWithoutDiscount" },
+ { data: "totalPriceWithoutDiscount" },
{ data: "mediaResources" },
{ data: "productUniqueName" },
{ data: "productDisplayName" },
{ data: "skuName" },
{ data: "skuDescription" },
{ data: "currency" },
- { data: "unitPrice" },
- { data: "totalPrice" },
- { data: "totalDiscount" },
{ data: "inventory" },
{ data: "isInvalid" },
]
diff --git a/samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/20230408062955_ImplementedProductDiscounts.Designer.cs b/samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/20230408062955_ImplementedProductDiscounts.Designer.cs
new file mode 100644
index 00000000..6adb4a9e
--- /dev/null
+++ b/samples/EShopSample/aspnet-core/src/EShopSample.EntityFrameworkCore/Migrations/20230408062955_ImplementedProductDiscounts.Designer.cs
@@ -0,0 +1,6421 @@
+//
+using System;
+using EShopSample.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.Abp.EntityFrameworkCore;
+
+#nullable disable
+
+namespace EShopSample.Migrations
+{
+ [DbContext(typeof(EShopSampleDbContext))]
+ [Migration("20230408062955_ImplementedProductDiscounts")]
+ partial class ImplementedProductDiscounts
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
+ .HasAnnotation("ProductVersion", "7.0.1")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("EasyAbp.BookingService.AssetCategories.AssetCategory", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AssetDefinitionName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DefaultPeriodUsable")
+ .HasColumnType("int");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("Disabled")
+ .HasColumnType("bit");
+
+ b.Property("DisplayName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("Level")
+ .HasColumnType("int");
+
+ b.Property("ParentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("PeriodSchemeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("EasyAbpBookingServiceAssetCategories", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.BookingService.AssetOccupancies.AssetOccupancy", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Asset")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("AssetDefinitionName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("AssetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("Date")
+ .HasColumnType("datetime2");
+
+ b.Property("Duration")
+ .HasColumnType("time");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("OccupierName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("OccupierUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("StartingTime")
+ .HasColumnType("time");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("Volume")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Date", "OccupierUserId");
+
+ b.HasIndex("Date", "AssetId", "StartingTime", "Duration");
+
+ b.ToTable("EasyAbpBookingServiceAssetOccupancies", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.BookingService.AssetOccupancyCounts.AssetOccupancyCount", b =>
+ {
+ b.Property("Date")
+ .HasColumnType("datetime2");
+
+ b.Property("AssetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("StartingTime")
+ .HasColumnType("time");
+
+ b.Property("Duration")
+ .HasColumnType("time");
+
+ b.Property("Asset")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("Volume")
+ .HasColumnType("int");
+
+ b.HasKey("Date", "AssetId", "StartingTime", "Duration");
+
+ b.ToTable("EasyAbpBookingServiceAssetOccupancyCounts", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.BookingService.AssetPeriodSchemes.AssetPeriodScheme", b =>
+ {
+ b.Property("Date")
+ .HasColumnType("datetime2");
+
+ b.Property("AssetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("PeriodSchemeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Date", "AssetId");
+
+ b.ToTable("EasyAbpBookingServiceAssetPeriodSchemes", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.BookingService.AssetSchedules.AssetSchedule", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AssetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("Date")
+ .HasColumnType("datetime2");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("PeriodId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("PeriodSchemeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("PeriodUsable")
+ .HasColumnType("int");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Date", "AssetId", "PeriodSchemeId");
+
+ b.ToTable("EasyAbpBookingServiceAssetSchedules", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.BookingService.Assets.Asset", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AssetCategoryId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AssetDefinitionName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DefaultPeriodUsable")
+ .HasColumnType("int");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("Disabled")
+ .HasColumnType("bit");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("PeriodSchemeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Priority")
+ .HasColumnType("int");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("Volume")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("EasyAbpBookingServiceAssets", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.BookingService.PeriodSchemes.Period", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Duration")
+ .HasColumnType("time");
+
+ b.Property("PeriodSchemeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("StartingTime")
+ .HasColumnType("time");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PeriodSchemeId");
+
+ b.ToTable("EasyAbpBookingServicePeriods", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.BookingService.PeriodSchemes.PeriodScheme", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDefault")
+ .HasColumnType("bit");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.ToTable("EasyAbpBookingServicePeriodSchemes", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.EShop.Orders.Orders.Order", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ActualTotalPrice")
+ .HasColumnType("decimal(20,8)");
+
+ b.Property("CanceledTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CancellationReason")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CompletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("Currency")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CustomerRemark")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CustomerUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("OrderNumber")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("OrderStatus")
+ .HasColumnType("int");
+
+ b.Property("PaidTime")
+ .HasColumnType("datetime2");
+
+ b.Property("PaymentExpiration")
+ .HasColumnType("datetime2");
+
+ b.Property("PaymentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ProductTotalPrice")
+ .HasColumnType("decimal(20,8)");
+
+ b.Property("ReducedInventoryAfterPaymentTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ReducedInventoryAfterPlacingTime")
+ .HasColumnType("datetime2");
+
+ b.Property("RefundAmount")
+ .HasColumnType("decimal(20,8)");
+
+ b.Property("StaffRemark")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("StoreId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("TotalDiscount")
+ .HasColumnType("decimal(20,8)");
+
+ b.Property("TotalPrice")
+ .HasColumnType("decimal(20,8)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrderNumber")
+ .IsUnique()
+ .HasFilter("[OrderNumber] IS NOT NULL");
+
+ b.ToTable("EasyAbpEShopOrdersOrders", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.EShop.Orders.Orders.OrderDiscount", b =>
+ {
+ b.Property("OrderId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("OrderLineId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("Key")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("DiscountedAmount")
+ .HasColumnType("decimal(20,8)");
+
+ b.Property("DisplayName")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("OrderId", "OrderLineId", "Name", "Key");
+
+ b.ToTable("EasyAbpEShopOrdersOrderDiscounts", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.EShop.Orders.Orders.OrderExtraFee", b =>
+ {
+ b.Property("OrderId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("Key")
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("DisplayName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Fee")
+ .HasColumnType("decimal(20,8)");
+
+ b.Property("RefundAmount")
+ .HasColumnType("decimal(20,8)");
+
+ b.HasKey("OrderId", "Name", "Key");
+
+ b.ToTable("EasyAbpEShopOrdersOrderExtraFees", (string)null);
+ });
+
+ modelBuilder.Entity("EasyAbp.EShop.Orders.Orders.OrderLine", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ActualTotalPrice")
+ .HasColumnType("decimal(20,8)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property