✨ 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