public ProductAsDiscount GetProductAsDiscount(DiscountType disType, Guid productId)
 {
     ProductAsDiscount pad = new ProductAsDiscount();
     if (discountLine.OfType<ProductAsDiscount>().Any(p => p.DiscountType == disType && p.ProductId == productId))
     {
         pad = discountLine.OfType<ProductAsDiscount>().FirstOrDefault(p => p.DiscountType == disType && p.ProductId == productId);
     }
     else
     {
         pad.ProductId = productId;
         pad.DiscountType = disType;
         discountLine.Add(pad);
     }
     return pad;
 }
        public ProductAsDiscount GetFOCCertainValue(decimal amount)
        {
            CertainValueCertainProductDiscount certainvalueDiscount = _certainValueCertainProduct.GetByAmount(amount);
            if (certainvalueDiscount != null)
            {
                try
                {
                    ProductRef certainProduct = certainvalueDiscount.CurrentProduct;
                    decimal certainProductQty = certainvalueDiscount.CurrentQuantity;
                    //cn::
                    decimal threshold = certainvalueDiscount.InitialValue;
                    int timesToApplyThreshold = (int)(amount / threshold);
                    ProductAsDiscount ad = new ProductAsDiscount
                    {
                        ProductId = certainProduct.ProductId,
                        DiscountType = DiscountType.CertainValueCertainProductDiscount,
                        Quantity = certainProductQty,
                    };
                    if (ad.Quantity > 0)
                        return ad;
                }
                catch (Exception ex) { }

            }
            return null;
        }
        public List<DiscountBase> GetDiscountSummary(List<OrderDiscountLineItem> productItems, Guid outletId)
        {
            discountLine = new List<DiscountBase>();
            var outlet = _costCentreService.GetById(outletId) as Outlet;
            if(outlet==null)
                throw new ArgumentException("Invalid Outlet Id");
            if (outlet.OutletProductPricingTier == null)
                throw new ArgumentException("Invalid Outlet Pricing Tier");
            ProductPricingTier tier = _productPricingTierService.GetById(outlet.OutletProductPricingTier.Id);
         
            decimal totalAmount = productItems.Sum(s => s.TotalPrice);

            #region Salevalue Discount
            SaleValueDiscount salevalueDiscount = _SaleValueDiscountService.GetCurrentDiscount(totalAmount,tier.Id);
            if (salevalueDiscount!=null)
            {
                decimal rate = salevalueDiscount.CurrentRate;
                decimal sd = rate*totalAmount;
                AmountDiscount ad = new AmountDiscount
                {
                    DiscountAmount = sd,
                    DiscountType = DiscountType.SaleValueDiscount,
                };
                AddDiscount(ad);
            }
            #endregion
            
            #region Product Discount
            foreach (OrderDiscountLineItem item in productItems)
            {
                try
                {
                    ProductDiscount pd = _productDiscount.GetProductDiscount(item.ProductId, tier.Id);
                    decimal rate = pd.CurrentDiscountRate(item.Quantity);
                    decimal issuedPd = rate * item.TotalPrice;
                    AmountDiscount ad = new AmountDiscount
                                            {
                                                DiscountAmount = issuedPd,
                                                DiscountType = DiscountType.ProductDiscount,
                                            };
                    AddDiscount(ad);
                }
                catch
                {
                }
            }
            #endregion

            #region Customer Discount
            if (outlet.DiscountGroup!=null)
            {
                foreach (OrderDiscountLineItem item in productItems)
                {
                    ProductGroupDiscount pgd = _productGroupDiscountService.GetCurrentCustomerDiscount(outlet.DiscountGroup.Id,item.ProductId,item.Quantity);
                    if (pgd != null)
                    {
                        decimal rate = pgd.CurrentDiscount();
                        decimal issuedPd = rate*item.TotalPrice;
                        if (issuedPd > 0)
                        {
                            AmountDiscount ad = new AmountDiscount
                            {
                                DiscountAmount = issuedPd,
                                DiscountType = DiscountType.GroupDiscount,
                            };
                            AddDiscount(ad);
                        }
                    }
                }

            }
            #endregion 

            #region Promotion
            foreach (OrderDiscountLineItem item in productItems)
            {
                PromotionDiscount pd = _promotionDiscountService.GetAll()
                    .Where(p => p.ProductRef.ProductId == item.ProductId).FirstOrDefault();
                if (pd != null)
                {
                    try
                    {
                        decimal rate = pd.CurrentDiscountRate;
                        decimal issuedPd = rate*item.TotalPrice;
                        if (issuedPd > 0)
                        {
                            AmountDiscount ad = new AmountDiscount
                            {
                                DiscountAmount = issuedPd,
                                DiscountType = DiscountType.PromotionDiscount,
                            };
                            AddDiscount(ad);
                        }
                        ProductRef pRef = pd.CurrentFreeOfChargeProduct;
                        decimal freequantity =  pd.CurrentFreeOfChargeQuantity;
                        if(pRef!= null && pRef.ProductId!=Guid.Empty)
                        {
                            ProductAsDiscount ad = new ProductAsDiscount
                            {
                                ProductId = pRef.ProductId,
                                DiscountType = DiscountType.PromotionDiscount,
                                Quantity = freequantity
                            };
                            AddDiscount(ad);
                        }
                       
                    }catch(Exception)
                    {
                    }
                }
            }
            #endregion

            #region Free of charge
            foreach (OrderDiscountLineItem item in productItems)
            {
                if(_freeOfChargeDiscountService.IsProductFreeOfCharge(item.ProductId))
                {
                    AmountDiscount ad = new AmountDiscount
                    {
                        DiscountAmount = item.TotalPrice,
                        DiscountType = DiscountType.FreeOfChargeDiscount,
                    };
                    AddDiscount(ad);
                }
            }

            #endregion

            #region Certain Value Certain Product
            CertainValueCertainProductDiscount certainvalueDiscount = _certainValueCertainProduct.GetByAmount(totalAmount);
            if (certainvalueDiscount != null)
            {
                try
                {
                    ProductRef certainProduct = certainvalueDiscount.CurrentProduct;
                    decimal certainProductQty = certainvalueDiscount.CurrentQuantity;
                    ProductAsDiscount ad = new ProductAsDiscount
                                               {
                                                   ProductId = certainProduct.ProductId,
                                                   DiscountType = DiscountType.CertainValueCertainProductDiscount,
                                                   Quantity = certainProductQty
                                               };
                    AddDiscount(ad);
                }catch(Exception)
                {
                    
                }

            }
            #endregion


            return discountLine;
        }
        public List<ProductAsDiscount> GetFOCCertainProduct(Guid ProductId, decimal quantity)
        {
            List<ProductAsDiscount> ls = new List<ProductAsDiscount>();
            PromotionDiscount pd = _promotionDiscountRepository.GetByProductId(ProductId);
            if (pd != null)
            {
                try
                {
                    //ProductRef pRef = pd.CurrentFreeProduct(quantity);
                    //decimal freequantity = pd.CurrentFreeProductQuantity(quantity);
                    //cn::
                    ;

                    PromotionDiscount.PromotionDiscountItem promotionItem = pd.AwardedPromotionDiscountItem(quantity);
                    //decimal threshold = pd.CurrentParentProductQuantity;
                    decimal threshold = promotionItem.ParentProductQuantity;
                    decimal timesToApplyThreshold = (int)(quantity / threshold);
                    ProductRef pRef = promotionItem.FreeOfChargeProduct;
                    decimal freequantity = promotionItem.FreeOfChargeQuantity;

                    if (pRef != null && pRef.ProductId != Guid.Empty)
                    {
                        ProductAsDiscount ad = new ProductAsDiscount
                        {
                            ProductId = pRef.ProductId,
                            DiscountType = DiscountType.PromotionDiscount,
                            Quantity = (freequantity * timesToApplyThreshold)
                        };
                        if (ad.Quantity > 0)
                            ls.Add(ad);
                    }
                }
                catch (Exception ex)
                {
                }
            }
            return ls;
        }
        public List<ProductAsDiscount> GetFOCCertainProduct(Guid ProductId, decimal quantity)
        {
            var ls = new List<ProductAsDiscount>();
            PromotionDiscount pd = _promotionDiscountService.GetCurrentDiscount(ProductId);
            if (pd != null)
            {
               

                    PromotionDiscount.PromotionDiscountItem promotionItem = pd.AwardedPromotionDiscountItem(quantity);
                    if (promotionItem != null)
                    {
                        //decimal threshold = pd.CurrentParentProductQuantity;
                        decimal threshold = promotionItem.ParentProductQuantity;
                        decimal timesToApplyThreshold = (int) (quantity/threshold);
                        ProductRef pRef = promotionItem.FreeOfChargeProduct;
                        decimal freequantity = promotionItem.FreeOfChargeQuantity;

                        if (pRef != null && pRef.ProductId != Guid.Empty)
                        {
                            ProductAsDiscount ad = new ProductAsDiscount
                                                       {
                                                           ProductId = pRef.ProductId,
                                                           DiscountType = DiscountType.PromotionDiscount,
                                                           Quantity = (freequantity*timesToApplyThreshold)
                                                       };
                            if (ad.Quantity > 0)
                                ls.Add(ad);
                        }
                    }

            }
            return ls;
        }