private void CheckVoucherUsed(string VoucherCode)
        {
            IVoucherService voucherService = DependencyUtils.Resolve <IVoucherService>();

            if (!string.IsNullOrEmpty(VoucherCode))
            {
                var voucher = voucherService.GetVoucherIsNotUsedAndCode(VoucherCode);
                if (voucher.MembershipCardId == null)
                {
                    voucher.UsedQuantity++;
                    if (voucher.UsedQuantity >= voucher.Quantity)
                    {
                        voucher.isUsed = true;
                    }
                    var voucherVM = new VoucherAPIViewModel(voucher);
                    voucher = voucherVM.ToEntity();
                    voucherService.Update(voucher);
                }
                else
                {
                    voucher.isUsed = true;
                    var voucherVM = new VoucherAPIViewModel(voucher);
                    voucher = voucherVM.ToEntity();
                    voucherService.Update(voucher);
                }
            }
        }
        public static PromotionRule checkPromotionRule(OrderAPIViewModel order, int quantity, OrderDetailAPIViewModel od)
        {
            #region call service
            IVoucherService         voucherService         = DependencyUtils.Resolve <IVoucherService>();
            IPromotionService       promotionService       = DependencyUtils.Resolve <IPromotionService>();
            IPromotionDetailService promotionDetailService = DependencyUtils.Resolve <IPromotionDetailService>();
            IProductService         productService         = DependencyUtils.Resolve <IProductService>();
            #endregion

            PromotionRule result = new PromotionRule
            {
                rule           = 0,
                discountAmount = 0
            };
            #region Voucher
            var voucher = voucherService.GetVoucherIsNotUsedAndCode(order.VoucherCode);
            if (voucher == null)
            {
                return(result);
            }
            #endregion


            //var voucher = voucherApi
            //TODO after have voucher
            int checkCountProduct = 0;//dùng check trường hợp gửi 2 đơn hàng giống nhau nhưng mỗi cái có 1 quantity

            //get date to get promotion is experied ??
            #region Promotion
            var      promotion = promotionService.GetPromotionByDateAndId(voucher.PromotionID);
            DateTime now       = DateTime.Now;

            if (promotion == null)
            {
                return(result);
            }
            else if (!(promotion.ApplyFromTime <= now.Hour && now.Hour <= promotion.ApplyToTime))
            {
                return(result);
            }

            #endregion
            #region PromtionDetail rule 1 min , max order???
            // loop to get total amount, final amount to get check in promotiondetail
            double finalAmount = 0;

            foreach (var item in order.OrderDetails)
            {
                finalAmount += (productService.GetProductById(item.ProductID).Price *item.Quantity);
            }

            var promotionDetail = promotionDetailService.GetDetailByCode(promotion.PromotionCode).FirstOrDefault();
            if (promotionDetail == null)
            {
                return(result);
            }
            //check promotion detail is have min, max order != null ???
            if (promotionDetail.MinOrderAmount != null || promotionDetail.MaxOrderAmount != null)
            {
                if (promotionDetail.MinOrderAmount != null && finalAmount < promotionDetail.MinOrderAmount)
                {
                    throw ApiException.Get(false, ConstantManager.MES_CREATE_ORDER_EXCEED_VOUCHER_MIN_MAX, ResultEnum.VoucherMin, HttpStatusCode.BadRequest);
                }
                else if (promotionDetail.MaxOrderAmount != null && finalAmount > promotionDetail.MaxOrderAmount)
                {
                    throw  ApiException.Get(false, ConstantManager.MES_CREATE_ORDER_EXCEED_VOUCHER_MIN_MAX, ResultEnum.VoucherMax, HttpStatusCode.BadRequest);
                }
                else
                {
                    try
                    {
                        double discountAmount = 0;//amount return
                        if (promotionDetail.DiscountRate != null && promotionDetail.DiscountRate > 0)
                        {
                            //nhân với phần trăm giảm giá và trả về số tiền lun
                            discountAmount = (productService.GetProductById(od.ProductID).Price *promotionDetail.DiscountRate.Value) / 100;
                        }
                        else if (promotionDetail.DiscountAmount != null && promotionDetail.DiscountAmount > 0)
                        {
                            //nếu giảm giá theo tiền mặt
                            discountAmount = Convert.ToDouble(promotionDetail.DiscountAmount.Value);
                        }
                        result.rule           = Models.ConstantManager.PROMOTION_RULE_1;
                        result.discountAmount = discountAmount;
                        return(result);
                    }
                    catch
                    {
                        result.rule           = 0;
                        result.discountAmount = 0;
                        return(result);
                    }
                }
            }
            #endregion

            #region rule 2 buy min, max quantity of each product
            else if (promotionDetail.BuyProductCode != null)
            {
                double discountAmount = 0;
                //check product code is in order ????
                bool checkProductCode = false;
                //list product discount
                List <ProductDiscount> listProductDiscount = new List <ProductDiscount>();
                // var pmDetail = promotionDetailApi.GetDetailByCode(promotion.PromotionCode);
                int     pDetailId         = voucher.PromotionDetailID == null ? 0 : voucher.PromotionDetailID.Value;
                var     pmDetail          = promotionDetailService.GetDetailById(pDetailId);
                decimal tmpDiscountAmount = 0;
                double  tmpDiscountRate   = 0;
                string  mesMinBuyProduct  = "";
                bool    checkCount        = true;//check quanitty min order buy
                var     tmpProductOrder   = productService.GetProductById(od.ProductID);

                bool checkCountProductQuantity = true; //false => đơn hàng gửi lên giống nhau nhưng ko đủ quantity min order,
                                                       //true => đơn hàng gửi lên giống nhau nhưng đủ quantity
                foreach (var item in order.OrderDetails)
                {
                    if (tmpProductOrder.Code == pmDetail.BuyProductCode)
                    {
                        checkCountProduct += item.Quantity;//cộng đồn quantity trong order
                        if (checkCountProduct < pmDetail.MinBuyQuantity)
                        {
                            checkCountProductQuantity = false;//false => đơn hàng gửi lên giống nhau nhưng ko đủ quantity min order,
                        }
                        else
                        {
                            checkCountProductQuantity = true;
                        }
                    }
                }
                if (pmDetail != null)
                {
                    if (tmpProductOrder.Code == pmDetail.BuyProductCode)
                    {
                        quantity         += od.Quantity;
                        tmpDiscountAmount = pmDetail.DiscountAmount == null ? 0 : pmDetail.DiscountAmount.Value * od.Quantity;
                        tmpDiscountRate   = pmDetail.DiscountRate == null ? 0 : pmDetail.DiscountRate.Value;
                        checkProductCode  = true;
                        if (quantity < pmDetail.MinBuyQuantity)
                        {
                            mesMinBuyProduct = pmDetail.MinBuyQuantity + " " + tmpProductOrder.ProductName;
                            checkCount       = false;
                        }
                    }
                    else
                    {
                        // checkCount = true;
                    }
                }

                try
                {
                    //if true => get list product discount
                    if (checkProductCode)
                    {
                        //check amount discount and rate, return value
                        if (tmpDiscountAmount > 0)
                        {
                            discountAmount = System.Convert.ToDouble(tmpDiscountAmount);
                        }
                        else if (tmpDiscountRate > 0)
                        {
                            discountAmount = (tmpProductOrder.Price * tmpDiscountRate * od.Quantity) / 100;
                        }
                    }
                    checkProductCode = false;
                    //return list product with discount amount, rate
                }
                catch
                {
                    result.rule           = 0;
                    result.discountAmount = 0;
                    result.quantity       = 0;
                    result.countProduct   = false;
                    return(result);
                }


                if (!checkCount && !checkCountProductQuantity)
                {
                    result.rule           = 0;
                    result.discountAmount = 0;
                    result.quantity       = quantity;
                    result.countProduct   = checkCountProductQuantity;
                    return(result);
                }
                result.rule           = ConstantManager.PROMOTION_RULE_2;
                result.discountAmount = discountAmount;
                result.quantity       = quantity;
                result.countProduct   = checkCountProductQuantity;
                return(result);
            }
            result.rule           = 0;
            result.discountAmount = 0;
            result.quantity       = 0;
            return(result);

            #endregion
        }
        public BaseResponse <OrderHistoryAPIViewModel> AddOrderFromMobile(OrderAPIViewModel order)
        {
            using (TransactionScope scope =
                       new TransactionScope(TransactionScopeOption.Required,
                                            new TransactionOptions {
                IsolationLevel = IsolationLevel.RepeatableRead
            }))
            {
                try
                {
                    #region call service
                    DateTime             time                = DataService.Models.Utils.GetCurrentDateTime();
                    IStoreService        storeService        = DependencyUtils.Resolve <IStoreService>();
                    IDeliveryInfoService deliveryInfoService = DependencyUtils.Resolve <IDeliveryInfoService>();
                    IVoucherService      voucherService      = DependencyUtils.Resolve <IVoucherService>();
                    var orderService   = DependencyUtils.Resolve <IOrderService>();
                    var productService = DependencyUtils.Resolve <IProductService>();
                    #endregion

                    #region set default order
                    order.DeliveryStatus = (int)DeliveryStatus.New;
                    //order.OrderType = (int)OrderTypeEnum.Delivery;
                    order.OrderStatus = (int)OrderStatusEnum.New;
                    order.InvoiceID   = ConstantManager.PREFIX_MOBILE + "-" + order.StoreID + "-" + InvoiceCodeGenerator.GenerateInvoiceCode(); // truyền mã hóa don
                    order.SourceType  = (int)SourceTypeEnum.Mobile;
                    order.IsSync      = false;
                    int paymentType = order.PaymentType;
                    #endregion

                    #region check customer existed
                    var customer = new CustomerDomain().GetCustomerById(order.CustomerID.Value);
                    if (customer == null)
                    {
                        throw ApiException.Get(false, ConstantManager.MES_CHECK_CUSTOMERID_FAIL, ResultEnum.CustomerNotFound, HttpStatusCode.NotFound);
                    }
                    #endregion
                    #region check parent and child OrderDetail
                    foreach (var item in order.OrderDetails)
                    {
                        if (item.ParentId == 0)
                        {
                            item.ParentId = null;
                        }
                        if (item.ParentId != null && item.ParentId > -1)
                        {
                            var parentOrderDetail = order.OrderDetails.FirstOrDefault(od => od.TmpDetailId == item.ParentId);
                            if (parentOrderDetail != null)
                            {
                                var listExtra = productService.getProductExtraById(parentOrderDetail.ProductID);
                                var check     = listExtra.FirstOrDefault(e => e.ProductID == item.ProductID);
                                if (check == null)
                                {
                                    throw ApiException.Get(false, ConstantManager.MES_CHILD_ORDERDETAIL_WRONG, ResultEnum.ChildOrderDetailWrong, HttpStatusCode.BadRequest);
                                }
                            }
                            else
                            {
                                throw ApiException.Get(false, ConstantManager.MES_PARENT_ORDERDETAIL_NOTFOUND, ResultEnum.ParentOrderDetailNotFound, HttpStatusCode.BadRequest);
                            }
                        }
                    }
                    #endregion

                    #region calculate price of order detail and order
                    #region check voucher existed
                    if (!string.IsNullOrEmpty(order.VoucherCode))
                    {
                        var voucher = voucherService.GetVoucherIsNotUsedAndCode(order.VoucherCode);
                        if (voucher == null)
                        {
                            throw ApiException.Get(false, ConstantManager.MES_CREATE_ORDER_NOT_FOUND_VOUCHER, ResultEnum.VoucherNotFound, HttpStatusCode.NotFound);
                        }
                    }
                    #endregion
                    CalculateOrderPrice(order, time);
                    #endregion

                    #region Update Order Type info
                    switch (order.OrderType)
                    {
                    case (int)OrderTypeEnum.MobileDelivery:
                        var deliveryInfo = deliveryInfoService.GetDeliveryById(order.DeliveryInfoId);
                        if (deliveryInfo != null && deliveryInfo.CustomerId == customer.CustomerID)
                        {
                            order.Receiver        = deliveryInfo.CustomerName;
                            order.DeliveryAddress = deliveryInfo.Address;
                            order.DeliveryPhone   = deliveryInfo.Phone;
                        }
                        else
                        {
                            throw ApiException.Get(true, ConstantManager.MES_DELIVERYID_WRONG, ResultEnum.DeliveryNotFound, HttpStatusCode.OK);
                        }
                        break;

                    case (int)OrderTypeEnum.AtStore:
                        order.DeliveryAddress = OrderTypeEnum.AtStore.DisplayName();
                        order.Receiver        = customer.Name;
                        order.DeliveryPhone   = customer.Phone;
                        break;

                    case (int)OrderTypeEnum.MobileTakeAway:
                        order.DeliveryAddress = OrderTypeEnum.MobileTakeAway.DisplayName();
                        order.Receiver        = customer.Name;
                        order.DeliveryPhone   = customer.Phone;
                        break;

                    default:
                        if (string.IsNullOrEmpty(order.DeliveryAddress))
                        {
                            throw ApiException.Get(true, ConstantManager.MES_ORDERTYPE_NOTSUPPORT, ResultEnum.OrderTypeNotSupport, HttpStatusCode.OK);
                        }
                        break;
                    }

                    #endregion

                    //get CallCenter storeid
                    //var mobileStore = storeService.GetStoresByBrandIdAndType(order.BrandId, (int)StoreTypeEnum.MobileApp).FirstOrDefault();
                    //if (mobileStore != null)
                    //{
                    //    order.StoreID = mobileStore.ID;
                    //}

                    order.GroupPaymentStatus = 0; //Tam thoi chua xài
                    order.PaymentStatus      = (int)OrderPaymentStatusEnum.Finish;
                    customer.BrandId         = order.BrandId;


                    #region Update payment
                    new PaymentDomain().UpdatePayment(order, customer, time);
                    #endregion
                    if (order.Payments.Count <= 0)
                    {
                        throw ApiException.Get(true, ConstantManager.MES_PAYMENTTYPE_NOTSUPPORT, ResultEnum.PaymenTypeNotSupport, HttpStatusCode.OK);
                    }
                    var orderTest = order.ToEntity();
                    var rs        = orderService.CreateOrder(orderTest);



                    if (rs == false)
                    {
                        throw ApiException.Get(false, ConstantManager.MES_CREATE_ORDER_FAIL, ResultEnum.CreateFail, HttpStatusCode.InternalServerError);
                    }

                    #region Update voucher after used
                    CheckVoucherUsed(order.VoucherCode);
                    #endregion
                    scope.Complete();
                    scope.Dispose();
                    var orderFinal = orderService.GetOrderByRenId(orderTest.RentID);
                    orderFinal.PaymentType = paymentType;
                    return(BaseResponse <OrderHistoryAPIViewModel> .Get(true, ConstantManager.MES_CREATE_ORDER_SUCCESS, orderFinal, ResultEnum.Success));
                }
                catch (Exception e)
                {
                    scope.Dispose();
                    if (e is ApiException)
                    {
                        throw e;
                    }
                    else
                    {
                        throw ApiException.Get(false, ConstantManager.MES_CREATE_ORDER_FAIL, ResultEnum.CreateFail, HttpStatusCode.InternalServerError);
                    }
                }
            }
        }