✨ Add support for brand-based discounts
* 🆕 Added support for brand discounts in `CalculateOrderDiscountCommandHandler` * 🏷️ Updated `DiscountCommands` class to include `BrandId` property * 🏗️ Introduced `BrandDiscount` class in `Discount.Aggregate.cs` with `Create` method * 🛠️ Modified `Order` class in `Order.Aggregate.cs` to handle `BrandId` * 🏷️ Updated `OrderProduct` class in `Order.Aggregate.cs` to include `BrandId` property * 🆕 Added `Brand` discount type to `DiscountType` enum * ✨ Enhanced `CreateDiscountCommandHandler` and `UpdateDiscountCommandHandler` for brand discounts * 🆕 Introduced `BrandDiscount` class in `BrandDiscount.cs` to represent brand-specific discounts Changes made by Amir.h Khademimaster
parent
a87bfee340
commit
96feec0b26
|
@ -73,6 +73,18 @@ public class CalculateOrderDiscountCommandHandler(
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (discount.Type == DiscountType.Brand)
|
||||||
|
{
|
||||||
|
|
||||||
|
var brandDiscount = await repositoryWrapper.SetRepository<BrandDiscount>()
|
||||||
|
.TableNoTracking
|
||||||
|
.FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
|
||||||
|
|
||||||
|
if (brandDiscount != null && !brandDiscount.IsExpired())
|
||||||
|
{
|
||||||
|
totalPrice = request.Order.OrderProducts.Where(op => op.BrandId == brandDiscount.BrandId).Sum(op => op.ProductCost);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (discount.Type == DiscountType.Subscriber)
|
else if (discount.Type == DiscountType.Subscriber)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Subscribe discount not implemented");
|
throw new NotImplementedException("Subscribe discount not implemented");
|
||||||
|
|
|
@ -21,7 +21,8 @@ bool IsForInvitation,
|
||||||
bool IsSpecialOffer,
|
bool IsSpecialOffer,
|
||||||
bool IsForFirstPurchase,
|
bool IsForFirstPurchase,
|
||||||
Guid ProductId,
|
Guid ProductId,
|
||||||
Guid CategoryId) : IRequest<DiscountLDto>;
|
Guid CategoryId,
|
||||||
|
Guid BrandId) : IRequest<DiscountLDto>;
|
||||||
|
|
||||||
public sealed record UpdateDiscountCommand(
|
public sealed record UpdateDiscountCommand(
|
||||||
Guid Id,
|
Guid Id,
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
namespace Netina.Domain.Entities.Discounts;
|
||||||
|
|
||||||
|
public partial class BrandDiscount : Discount
|
||||||
|
{
|
||||||
|
public BrandDiscount()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrandDiscount(string code, string description, int discountPercent, long discountAmount, bool hasCode, DiscountAmountType amountType, DiscountType type,
|
||||||
|
int count, bool immortal, DateTime startDate, DateTime expireDate, long priceFloor, bool hasPriceFloor, long priceCeiling,
|
||||||
|
bool hasPriceCeiling, bool isInfinity, long useCount, bool isForInvitation,
|
||||||
|
bool isForFirstPurchase, bool isSpecialOffer , Guid brandId)
|
||||||
|
: base(code, description, discountPercent, discountAmount, hasCode, amountType, type, count, startDate, expireDate, priceFloor, hasPriceFloor, priceCeiling, hasPriceCeiling, isInfinity, useCount,
|
||||||
|
isForInvitation, isSpecialOffer,isForFirstPurchase, immortal)
|
||||||
|
{
|
||||||
|
BrandId = brandId;
|
||||||
|
}
|
||||||
|
public Guid BrandId { get; internal set; }
|
||||||
|
public Brand? Brand { get; internal set; }
|
||||||
|
}
|
|
@ -39,6 +39,19 @@ public partial class Discount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public partial class BrandDiscount
|
||||||
|
{
|
||||||
|
public static BrandDiscount Create(string code, string description, int discountPercent, long discountAmount, bool hasCode, DiscountAmountType amountType, DiscountType type,
|
||||||
|
int count, bool immortal, DateTime startDate, DateTime expireDate, long priceFloor, bool hasPriceFloor, long priceCeiling,
|
||||||
|
bool hasPriceCeiling, bool isInfinity, long useCount, bool isForInvitation,
|
||||||
|
bool isForFirstPurchase, bool isSpecialOffer, Guid brandId)
|
||||||
|
{
|
||||||
|
return new BrandDiscount(code, description, discountPercent, discountAmount, hasCode, amountType, type, count, immortal, startDate,
|
||||||
|
expireDate, priceFloor, hasPriceFloor, priceCeiling, hasPriceCeiling, isInfinity, useCount,
|
||||||
|
isForInvitation, isForFirstPurchase, isSpecialOffer, brandId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public partial class ProductDiscount
|
public partial class ProductDiscount
|
||||||
{
|
{
|
||||||
public static ProductDiscount Create(string code, string description, int discountPercent, long discountAmount, bool hasCode, DiscountAmountType amountType, DiscountType type,
|
public static ProductDiscount Create(string code, string description, int discountPercent, long discountAmount, bool hasCode, DiscountAmountType amountType, DiscountType type,
|
||||||
|
|
|
@ -12,7 +12,10 @@ public partial class Order
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddToOrderBag(Guid productId, double cost, double costWithDiscount, bool hasDiscount, double packingCost, Guid categoryId, int count)
|
public void AddToOrderBag(Guid productId, double cost, double costWithDiscount, bool hasDiscount, double packingCost,
|
||||||
|
Guid categoryId,
|
||||||
|
Guid brandId,
|
||||||
|
int count)
|
||||||
{
|
{
|
||||||
var orderProduct = OrderProducts.FirstOrDefault(op => op.ProductId == productId);
|
var orderProduct = OrderProducts.FirstOrDefault(op => op.ProductId == productId);
|
||||||
if (orderProduct == null)
|
if (orderProduct == null)
|
||||||
|
@ -25,6 +28,7 @@ public partial class Order
|
||||||
OrderStatus.OrderBag,
|
OrderStatus.OrderBag,
|
||||||
productId,
|
productId,
|
||||||
categoryId,
|
categoryId,
|
||||||
|
brandId,
|
||||||
this.Id);
|
this.Id);
|
||||||
OrderProducts.Add(orderProduct);
|
OrderProducts.Add(orderProduct);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +48,10 @@ public partial class Order
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeOrderBag(Guid productId, double cost, double costWithDiscount, bool hasDiscount, double packingCost, Guid categoryId, int count)
|
public void ChangeOrderBag(Guid productId, double cost, double costWithDiscount, bool hasDiscount, double packingCost,
|
||||||
|
Guid categoryId,
|
||||||
|
Guid brandId,
|
||||||
|
int count)
|
||||||
{
|
{
|
||||||
var orderProduct = OrderProducts.FirstOrDefault(op => op.ProductId == productId);
|
var orderProduct = OrderProducts.FirstOrDefault(op => op.ProductId == productId);
|
||||||
if (orderProduct != null)
|
if (orderProduct != null)
|
||||||
|
@ -52,10 +59,10 @@ public partial class Order
|
||||||
if (orderProduct.Count > count)
|
if (orderProduct.Count > count)
|
||||||
RemoveFromOrderBag(productId, count);
|
RemoveFromOrderBag(productId, count);
|
||||||
else
|
else
|
||||||
AddToOrderBag(productId, cost, costWithDiscount, hasDiscount, packingCost, categoryId, count);
|
AddToOrderBag(productId, cost, costWithDiscount, hasDiscount, packingCost, categoryId,brandId, count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
AddToOrderBag(productId, cost, costWithDiscount, hasDiscount, packingCost, categoryId, count);
|
AddToOrderBag(productId, cost, costWithDiscount, hasDiscount, packingCost, categoryId, brandId, count);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,11 +172,16 @@ public partial class OrderProduct
|
||||||
OrderStatus orderProductStatus,
|
OrderStatus orderProductStatus,
|
||||||
Guid productId,
|
Guid productId,
|
||||||
Guid productCategoryId,
|
Guid productCategoryId,
|
||||||
|
Guid brandId,
|
||||||
Guid orderId)
|
Guid orderId)
|
||||||
{
|
{
|
||||||
var productCost = count * productFeeWithDiscount;
|
var productCost = count * productFeeWithDiscount;
|
||||||
var packingCost = count * packingFee;
|
var packingCost = count * packingFee;
|
||||||
return new OrderProduct(count, productFee, productFeeWithDiscount, hasDiscount, productCost, packingFee, packingCost, orderProductStatus, productId, productCategoryId, orderId);
|
return new OrderProduct(count, productFee,
|
||||||
|
productFeeWithDiscount, hasDiscount,
|
||||||
|
productCost, packingFee, packingCost,
|
||||||
|
orderProductStatus, productId,
|
||||||
|
productCategoryId, orderId,brandId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCount(int count)
|
public void SetCount(int count)
|
||||||
|
|
|
@ -19,7 +19,8 @@ public partial class OrderProduct : ApiEntity
|
||||||
OrderStatus orderProductStatus,
|
OrderStatus orderProductStatus,
|
||||||
Guid productId,
|
Guid productId,
|
||||||
Guid productCategoryId,
|
Guid productCategoryId,
|
||||||
Guid orderId)
|
Guid orderId,
|
||||||
|
Guid brandId)
|
||||||
{
|
{
|
||||||
Count = count;
|
Count = count;
|
||||||
ProductFee = productFee;
|
ProductFee = productFee;
|
||||||
|
@ -32,6 +33,7 @@ public partial class OrderProduct : ApiEntity
|
||||||
ProductCategoryId = productCategoryId;
|
ProductCategoryId = productCategoryId;
|
||||||
PackingFee = packingFee;
|
PackingFee = packingFee;
|
||||||
PackingCost = packingCost;
|
PackingCost = packingCost;
|
||||||
|
BrandId = brandId;
|
||||||
}
|
}
|
||||||
public int Count { get; internal set; }
|
public int Count { get; internal set; }
|
||||||
public double ProductFee { get; internal set; }
|
public double ProductFee { get; internal set; }
|
||||||
|
@ -43,6 +45,7 @@ public partial class OrderProduct : ApiEntity
|
||||||
public OrderStatus OrderProductStatus { get; internal set; }
|
public OrderStatus OrderProductStatus { get; internal set; }
|
||||||
|
|
||||||
public Guid ProductId { get; internal set; }
|
public Guid ProductId { get; internal set; }
|
||||||
|
public Guid BrandId { get; internal set; }
|
||||||
public Guid ProductCategoryId { get; internal set; }
|
public Guid ProductCategoryId { get; internal set; }
|
||||||
public Product? Product { get; internal set; }
|
public Product? Product { get; internal set; }
|
||||||
|
|
||||||
|
|
|
@ -9,5 +9,7 @@ public enum DiscountType
|
||||||
[Display(Name = "دسته ای")]
|
[Display(Name = "دسته ای")]
|
||||||
Category = 2,
|
Category = 2,
|
||||||
[Display(Name = "مشترکی")]
|
[Display(Name = "مشترکی")]
|
||||||
Subscriber = 3
|
Subscriber = 3,
|
||||||
|
[Display(Name = "برند")]
|
||||||
|
Brand = 4,
|
||||||
}
|
}
|
|
@ -48,6 +48,13 @@ public class CreateDiscountCommandHandler(IRepositoryWrapper repositoryWrapper)
|
||||||
request.IsForInvitation, request.IsForFirstPurchase, request.IsSpecialOffer, request.ProductId);
|
request.IsForInvitation, request.IsForFirstPurchase, request.IsSpecialOffer, request.ProductId);
|
||||||
repositoryWrapper.SetRepository<ProductDiscount>().Add(productDis);
|
repositoryWrapper.SetRepository<ProductDiscount>().Add(productDis);
|
||||||
break;
|
break;
|
||||||
|
case DiscountType.Brand:
|
||||||
|
var brandDis = BrandDiscount.Create(request.Code, request.Description, request.DiscountPercent, request.DiscountAmount, request.HasCode,
|
||||||
|
request.AmountType, request.Type, request.Count, request.IsImmortal, request.StartDate, request.ExpireDate, request.PriceFloor,
|
||||||
|
request.HasPriceFloor, request.PriceCeiling, request.HasPriceCeiling, request.IsInfinity, request.UseCount,
|
||||||
|
request.IsForInvitation, request.IsForFirstPurchase, request.IsSpecialOffer, request.BrandId);
|
||||||
|
repositoryWrapper.SetRepository<BrandDiscount>().Add(brandDis);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
var def = Discount.Create(request.Code, request.Description, request.DiscountPercent, request.DiscountAmount, request.HasCode,
|
var def = Discount.Create(request.Code, request.Description, request.DiscountPercent, request.DiscountAmount, request.HasCode,
|
||||||
request.AmountType, request.Type, request.Count, request.IsImmortal, request.StartDate, request.ExpireDate, request.PriceFloor,
|
request.AmountType, request.Type, request.Count, request.IsImmortal, request.StartDate, request.ExpireDate, request.PriceFloor,
|
||||||
|
|
|
@ -55,6 +55,23 @@ public class UpdateDiscountCommandHandler(IRepositoryWrapper repositoryWrapper)
|
||||||
productDis.CreatedBy = productEnt.CreatedBy;
|
productDis.CreatedBy = productEnt.CreatedBy;
|
||||||
repositoryWrapper.SetRepository<ProductDiscount>().Update(productDis);
|
repositoryWrapper.SetRepository<ProductDiscount>().Update(productDis);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DiscountType.Brand:
|
||||||
|
var brandEnt = await repositoryWrapper.SetRepository<BrandDiscount>().TableNoTracking.FirstOrDefaultAsync(d => d.Id == request.Id, cancellationToken);
|
||||||
|
if (brandEnt == null)
|
||||||
|
throw new AppException("Discount not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
var brandDis = BrandDiscount.Create(request.Code, request.Description,
|
||||||
|
request.DiscountPercent, request.DiscountAmount, request.HasCode,
|
||||||
|
request.AmountType, request.Type, request.Count, request.IsImmortal,
|
||||||
|
request.StartDate, request.ExpireDate, request.PriceFloor, request.HasPriceFloor,
|
||||||
|
request.PriceCeiling, request.HasPriceCeiling, request.IsInfinity,
|
||||||
|
request.UseCount, request.IsForInvitation, request.IsForFirstPurchase, request.IsSpecialOffer, request.ProductId);
|
||||||
|
brandDis.Id = brandEnt.Id;
|
||||||
|
brandDis.CreatedAt = brandEnt.CreatedAt;
|
||||||
|
brandDis.CreatedBy = brandEnt.CreatedBy;
|
||||||
|
repositoryWrapper.SetRepository<BrandDiscount>().Update(brandDis);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
await repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue