mirror of https://github.com/EasyAbp/EShop.git
78 changed files with 7616 additions and 266 deletions
@ -1,36 +1,40 @@ |
|||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using Volo.Abp.Application.Dtos; |
using Volo.Abp.Application.Dtos; |
||||
using Volo.Abp.Data; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Products.Products.Dtos |
namespace EasyAbp.EShop.Products.Products.Dtos |
||||
{ |
{ |
||||
[Serializable] |
[Serializable] |
||||
public class ProductSkuDto : ExtensibleFullAuditedEntityDto<Guid>, IProductSku |
public class ProductSkuDto : ExtensibleFullAuditedEntityDto<Guid>, IProductSku, IHasFullDiscountsInfo |
||||
{ |
{ |
||||
public List<Guid> AttributeOptionIds { get; set; } |
public List<Guid> AttributeOptionIds { get; set; } |
||||
|
|
||||
public string Name { get; set; } |
public string Name { get; set; } |
||||
|
|
||||
public string Currency { get; set; } |
public string Currency { get; set; } |
||||
|
|
||||
public decimal? OriginalPrice { get; set; } |
public decimal? OriginalPrice { get; set; } |
||||
|
|
||||
|
public decimal PriceWithoutDiscount { get; set; } |
||||
|
|
||||
public decimal Price { get; set; } |
public decimal Price { get; set; } |
||||
|
|
||||
public decimal DiscountedPrice { get; set; } |
public List<ProductDiscountInfoModel> ProductDiscounts { get; set; } = new(); |
||||
|
|
||||
|
public List<OrderDiscountPreviewInfoModel> OrderDiscountPreviews { get; set; } = new(); |
||||
|
|
||||
public int Inventory { get; set; } |
public int Inventory { get; set; } |
||||
|
|
||||
public long Sold { get; set; } |
public long Sold { get; set; } |
||||
|
|
||||
public int OrderMinQuantity { get; set; } |
public int OrderMinQuantity { get; set; } |
||||
|
|
||||
public int OrderMaxQuantity { get; set; } |
public int OrderMaxQuantity { get; set; } |
||||
|
|
||||
public TimeSpan? PaymentExpireIn { get; set; } |
public TimeSpan? PaymentExpireIn { get; set; } |
||||
|
|
||||
public string MediaResources { get; set; } |
public string MediaResources { get; set; } |
||||
|
|
||||
public Guid? ProductDetailId { get; set; } |
public Guid? ProductDetailId { get; set; } |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products; |
||||
|
|
||||
|
public class DiscountAmountOverflowException : BusinessException |
||||
|
{ |
||||
|
public DiscountAmountOverflowException() : base(ProductsErrorCodes.DiscountAmountOverflow) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// When the discount begins to take effect.
|
||||
|
/// </summary>
|
||||
|
public DateTime? FromTime { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// When the discount ends.
|
||||
|
/// </summary>
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products; |
||||
|
|
||||
|
public class DiscountsInfoModel : IHasDiscountsInfo |
||||
|
{ |
||||
|
public List<ProductDiscountInfoModel> ProductDiscounts { get; set; } |
||||
|
|
||||
|
public List<OrderDiscountPreviewInfoModel> OrderDiscountPreviews { get; set; } |
||||
|
|
||||
|
public DiscountsInfoModel() |
||||
|
{ |
||||
|
ProductDiscounts = new List<ProductDiscountInfoModel>(); |
||||
|
OrderDiscountPreviews = new List<OrderDiscountPreviewInfoModel>(); |
||||
|
} |
||||
|
|
||||
|
public DiscountsInfoModel(List<ProductDiscountInfoModel> productDiscounts, |
||||
|
List<OrderDiscountPreviewInfoModel> orderDiscountPreviews) |
||||
|
{ |
||||
|
ProductDiscounts = productDiscounts ?? new List<ProductDiscountInfoModel>(); |
||||
|
OrderDiscountPreviews = orderDiscountPreviews ?? new List<OrderDiscountPreviewInfoModel>(); |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products; |
||||
|
|
||||
|
public interface IHasDiscountsInfo |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Price of the ProductSku has been subtracted from these product discounts.
|
||||
|
/// </summary>
|
||||
|
List<ProductDiscountInfoModel> ProductDiscounts { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// These order discount previews do not change the Price. They will be effective after placing an order.
|
||||
|
/// </summary>
|
||||
|
List<OrderDiscountPreviewInfoModel> OrderDiscountPreviews { get; } |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace EasyAbp.EShop.Products.Products; |
||||
|
|
||||
|
public interface IHasFullDiscountsInfo : IHasDiscountsInfo |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The realtime price without subtracting the discount amount.
|
||||
|
/// </summary>
|
||||
|
decimal PriceWithoutDiscount { get; } |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Products.Products; |
||||
|
|
||||
|
public class InvalidTimePeriodException : BusinessException |
||||
|
{ |
||||
|
public InvalidTimePeriodException() : base(ProductsErrorCodes.InvalidTimePeriod) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 DiscountAsync(ProductDiscountContext context); |
||||
{ |
|
||||
Task<decimal> GetDiscountedPriceAsync(Product product, ProductSku productSku, decimal currentPrice); |
|
||||
} |
|
||||
} |
} |
||||
@ -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; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// It's a sum of the amount of product discounts which in effect at the current time (this.<see cref="Now"/>).
|
||||
|
/// </summary>
|
||||
|
public decimal DiscountedAmount => this.GetProductDiscountsDiscountedAmount(Now); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// It has been subtracted from the product discounts which in effect at the current time (this.<see cref="Now"/>).
|
||||
|
/// </summary>
|
||||
|
public decimal DiscountedPrice => PriceWithoutDiscount - DiscountedAmount; |
||||
|
|
||||
|
public List<ProductDiscountInfoModel> ProductDiscounts { get; } = new(); |
||||
|
|
||||
|
public List<OrderDiscountPreviewInfoModel> OrderDiscountPreviews { get; } = new(); |
||||
|
|
||||
|
public PriceDataModel(decimal priceWithoutDiscount, IClock clock) |
||||
{ |
{ |
||||
public decimal Price { get; set; } |
if (PriceWithoutDiscount < decimal.Zero) |
||||
|
{ |
||||
public decimal DiscountedPrice { get; set; } |
throw new OverflowException(); |
||||
|
} |
||||
|
|
||||
|
Now = clock.Now; |
||||
|
PriceWithoutDiscount = priceWithoutDiscount; |
||||
} |
} |
||||
} |
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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<IHasAttributeOptionIds>()) |
|
||||
{ |
|
||||
b.Property(nameof(IHasAttributeOptionIds.AttributeOptionIds)) |
|
||||
.HasConversion<AttributeOptionIdsValueConverter>() |
|
||||
.Metadata.SetValueComparer(new AttributeOptionIdsValueComparer()); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueComparer.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueComparer.cs
2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueComparer.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueComparer.cs
2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueConverter.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueConverter.cs
2
modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/AttributeOptionIds/AttributeOptionIdsValueConverter.cs → modules/EasyAbp.EShop.Products/src/EasyAbp.EShop.Products.EntityFrameworkCore/EasyAbp/EShop/Products/EntityFrameworkCore/ValueMappings/AttributeOptionIdsValueConverter.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<List<ProductDiscountInfoModel>> |
||||
|
{ |
||||
|
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<List<OrderDiscountPreviewInfoModel>> |
||||
|
{ |
||||
|
public OrderDiscountPreviewsInfoValueComparer() |
||||
|
: base( |
||||
|
(d1, d2) => d1.SequenceEqual(d2), |
||||
|
d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())), |
||||
|
d => new List<OrderDiscountPreviewInfoModel>(d)) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -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<List<ProductDiscountInfoModel>, string> |
||||
|
{ |
||||
|
public ProductDiscountsInfoValueConverter() : base( |
||||
|
v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null), |
||||
|
v => JsonSerializer.Deserialize<List<ProductDiscountInfoModel>>(v, (JsonSerializerOptions)null)) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class OrderDiscountPreviewsInfoValueConverter : ValueConverter<List<OrderDiscountPreviewInfoModel>, string> |
||||
|
{ |
||||
|
public OrderDiscountPreviewsInfoValueConverter() : base( |
||||
|
v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null), |
||||
|
v => JsonSerializer.Deserialize<List<OrderDiscountPreviewInfoModel>>(v, (JsonSerializerOptions)null)) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -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<IHasAttributeOptionIds>()) |
||||
|
{ |
||||
|
b.Property(nameof(IHasAttributeOptionIds.AttributeOptionIds)) |
||||
|
.HasConversion<AttributeOptionIdsValueConverter>() |
||||
|
.Metadata.SetValueComparer(new AttributeOptionIdsValueComparer()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void TryConfigureDiscountsInfo(this EntityTypeBuilder b) |
||||
|
{ |
||||
|
if (b.Metadata.ClrType.IsAssignableTo<IHasDiscountsInfo>()) |
||||
|
{ |
||||
|
b.Property(nameof(IHasDiscountsInfo.ProductDiscounts)) |
||||
|
.HasConversion<ProductDiscountsInfoValueConverter>() |
||||
|
.Metadata.SetValueComparer(new ProductDiscountsInfoValueComparer()); |
||||
|
b.Property(nameof(IHasDiscountsInfo.OrderDiscountPreviews)) |
||||
|
.HasConversion<OrderDiscountPreviewsInfoValueConverter>() |
||||
|
.Metadata.SetValueComparer(new OrderDiscountPreviewsInfoValueComparer()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<ProductDiscountInfoModel> |
||||
|
{ |
||||
|
// 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<OrderDiscountPreviewInfoModel> |
||||
|
{ |
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IProductDiscountProvider, DemoProductDiscountProvider>(); |
||||
|
base.AfterAddApplication(services); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Get_Product_With_Discount() |
||||
|
{ |
||||
|
var productAppService = GetRequiredService<IProductAppService>(); |
||||
|
|
||||
|
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(); |
||||
|
} |
||||
|
} |
||||
@ -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 class ProductDataModel : IProductData |
||||
{ |
{ |
||||
public string MediaResources { get; set; } |
public string MediaResources { get; set; } |
||||
|
|
||||
public string ProductUniqueName { get; set; } |
public string ProductUniqueName { get; set; } |
||||
|
|
||||
public string ProductDisplayName { get; set; } |
public string ProductDisplayName { get; set; } |
||||
|
|
||||
public string SkuName { get; set; } |
public string SkuName { get; set; } |
||||
|
|
||||
public string SkuDescription { get; set; } |
public string SkuDescription { get; set; } |
||||
|
|
||||
public string Currency { get; set; } |
public string Currency { get; set; } |
||||
|
|
||||
public decimal UnitPrice { get; set; } |
public decimal PriceWithoutDiscount { get; set; } |
||||
|
|
||||
public decimal TotalPrice { get; set; } |
public List<ProductDiscountInfoModel> ProductDiscounts { get; set; } = new(); |
||||
|
|
||||
public decimal TotalDiscount { get; set; } |
public List<OrderDiscountPreviewInfoModel> OrderDiscountPreviews { get; set; } = new(); |
||||
|
|
||||
public int Inventory { get; set; } |
public int Inventory { get; set; } |
||||
} |
} |
||||
} |
} |
||||
@ -1,27 +1,8 @@ |
|||||
using System; |
|
||||
using JetBrains.Annotations; |
|
||||
using Volo.Abp.Data; |
|
||||
|
|
||||
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems; |
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 SetIsInvalid(bool isInvalid); |
||||
|
|
||||
void UpdateProductData(int quantity, IProductData productData); |
void Update(int quantity, IProductData productData); |
||||
} |
} |
||||
@ -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; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// PriceWithoutDiscount * Quantity
|
||||
|
/// </summary>
|
||||
|
decimal TotalPriceWithoutDiscount { get; } |
||||
|
|
||||
|
bool IsInvalid { get; } |
||||
|
} |
||||
@ -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 MediaResources { get; } |
||||
|
|
||||
string ProductUniqueName { get; } |
string ProductUniqueName { get; } |
||||
|
|
||||
string ProductDisplayName { get; } |
string ProductDisplayName { get; } |
||||
|
|
||||
string SkuName { get; } |
string SkuName { get; } |
||||
|
|
||||
string SkuDescription { get; } |
string SkuDescription { get; } |
||||
|
|
||||
string Currency { get; } |
string Currency { get; } |
||||
|
|
||||
decimal UnitPrice { get; } |
|
||||
|
|
||||
decimal TotalPrice { get; } |
|
||||
|
|
||||
decimal TotalDiscount { get; } |
|
||||
|
|
||||
int Inventory { get; } |
int Inventory { get; } |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems; |
||||
|
|
||||
|
public interface IServerSideBasketItemInfo : IBasketItemInfo |
||||
|
{ |
||||
|
Guid UserId { get; } |
||||
|
} |
||||
@ -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<List<ProductDiscountInfoModel>> |
||||
|
{ |
||||
|
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<List<OrderDiscountPreviewInfoModel>> |
||||
|
{ |
||||
|
public OrderDiscountPreviewsInfoValueComparer() |
||||
|
: base( |
||||
|
(d1, d2) => d1.SequenceEqual(d2), |
||||
|
d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())), |
||||
|
d => new List<OrderDiscountPreviewInfoModel>(d)) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -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<List<ProductDiscountInfoModel>, string> |
||||
|
{ |
||||
|
public ProductDiscountsInfoValueConverter() : base( |
||||
|
v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null), |
||||
|
v => JsonSerializer.Deserialize<List<ProductDiscountInfoModel>>(v, (JsonSerializerOptions)null)) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class OrderDiscountPreviewsInfoValueConverter : ValueConverter<List<OrderDiscountPreviewInfoModel>, string> |
||||
|
{ |
||||
|
public OrderDiscountPreviewsInfoValueConverter() : base( |
||||
|
v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null), |
||||
|
v => JsonSerializer.Deserialize<List<OrderDiscountPreviewInfoModel>>(v, (JsonSerializerOptions)null)) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -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<IHasDiscountsInfo>()) |
||||
|
{ |
||||
|
b.Property(nameof(IHasDiscountsInfo.ProductDiscounts)) |
||||
|
.HasConversion<ProductDiscountsInfoValueConverter>() |
||||
|
.Metadata.SetValueComparer(new ProductDiscountsInfoValueComparer()); |
||||
|
b.Property(nameof(IHasDiscountsInfo.OrderDiscountPreviews)) |
||||
|
.HasConversion<OrderDiscountPreviewsInfoValueConverter>() |
||||
|
.Metadata.SetValueComparer(new OrderDiscountPreviewsInfoValueComparer()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -0,0 +1,109 @@ |
|||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
#nullable disable |
||||
|
|
||||
|
namespace EShopSample.Migrations |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public partial class ImplementedProductDiscounts : Migration |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "TotalDiscount", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems"); |
||||
|
|
||||
|
migrationBuilder.RenameColumn( |
||||
|
name: "UnitPrice", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems", |
||||
|
newName: "TotalPriceWithoutDiscount"); |
||||
|
|
||||
|
migrationBuilder.RenameColumn( |
||||
|
name: "TotalPrice", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems", |
||||
|
newName: "PriceWithoutDiscount"); |
||||
|
|
||||
|
migrationBuilder.AddColumn<decimal>( |
||||
|
name: "MaximumPriceWithoutDiscount", |
||||
|
table: "EasyAbpEShopProductsProductViews", |
||||
|
type: "decimal(20,8)", |
||||
|
nullable: true); |
||||
|
|
||||
|
migrationBuilder.AddColumn<decimal>( |
||||
|
name: "MinimumPriceWithoutDiscount", |
||||
|
table: "EasyAbpEShopProductsProductViews", |
||||
|
type: "decimal(20,8)", |
||||
|
nullable: true); |
||||
|
|
||||
|
migrationBuilder.AddColumn<string>( |
||||
|
name: "OrderDiscountPreviews", |
||||
|
table: "EasyAbpEShopProductsProductViews", |
||||
|
type: "nvarchar(max)", |
||||
|
nullable: true); |
||||
|
|
||||
|
migrationBuilder.AddColumn<string>( |
||||
|
name: "ProductDiscounts", |
||||
|
table: "EasyAbpEShopProductsProductViews", |
||||
|
type: "nvarchar(max)", |
||||
|
nullable: true); |
||||
|
|
||||
|
migrationBuilder.AddColumn<string>( |
||||
|
name: "OrderDiscountPreviews", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems", |
||||
|
type: "nvarchar(max)", |
||||
|
nullable: true); |
||||
|
|
||||
|
migrationBuilder.AddColumn<string>( |
||||
|
name: "ProductDiscounts", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems", |
||||
|
type: "nvarchar(max)", |
||||
|
nullable: true); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "MaximumPriceWithoutDiscount", |
||||
|
table: "EasyAbpEShopProductsProductViews"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "MinimumPriceWithoutDiscount", |
||||
|
table: "EasyAbpEShopProductsProductViews"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "OrderDiscountPreviews", |
||||
|
table: "EasyAbpEShopProductsProductViews"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "ProductDiscounts", |
||||
|
table: "EasyAbpEShopProductsProductViews"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "OrderDiscountPreviews", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "ProductDiscounts", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems"); |
||||
|
|
||||
|
migrationBuilder.RenameColumn( |
||||
|
name: "TotalPriceWithoutDiscount", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems", |
||||
|
newName: "UnitPrice"); |
||||
|
|
||||
|
migrationBuilder.RenameColumn( |
||||
|
name: "PriceWithoutDiscount", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems", |
||||
|
newName: "TotalPrice"); |
||||
|
|
||||
|
migrationBuilder.AddColumn<decimal>( |
||||
|
name: "TotalDiscount", |
||||
|
table: "EasyAbpEShopPluginsBasketsBasketItems", |
||||
|
type: "decimal(20,8)", |
||||
|
nullable: false, |
||||
|
defaultValue: 0m); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue