public OrderAPIViewModel AddOrderFromPOS(OrderAPIViewModel model)
        {
            try
            {
                var status             = 0;
                var orderService       = DependencyUtils.Resolve <IOrderService>();
                var productService     = DependencyUtils.Resolve <IProductService>();
                var paymentService     = DependencyUtils.Resolve <IPaymentService>();
                var orderDetailService = DependencyUtils.Resolve <IOrderDetailService>();
                var orderDetailDomain  = new OrderDetailDomain();

                //Cập nhật status đơn hàng
                status = UpdateOrderStatus(model.OrderStatus, model.DeliveryStatus.Value);


                //API return success case
                var result = new OrderAPIViewModel()
                {
                    OrderStatus    = status,
                    InvoiceID      = model.OrderCode,
                    DeliveryStatus = model.DeliveryStatus,
                    CheckInPerson  = model.CheckInPerson,
                };

                //Check if order is existed in server
                var checkRent = orderService.GetOrderByInvoiceId(model.OrderCode);

                //Nếu chưa có sẽ add đơn hàng vào db server
                if (checkRent == null)
                {
                    result = AddOrder(status, model, result);
                }
                //Nếu đơn hàng đã có trên server sẽ update payment hoặc order detail
                else
                {
                    result = UpdateOrder(status, checkRent, model, result);
                }

                return(result);
            }
            catch (Exception ex)
            {
                return(new OrderAPIViewModel
                {
                    OrderStatus = model.OrderStatus,
                    InvoiceID = model.OrderCode,
                    DeliveryStatus = model.DeliveryStatus,
                    CheckInPerson = model.CheckInPerson,
                    //Something wrong, return old status
                });
            }
        }
        private OrderAPIViewModel AddOrder(int status, OrderAPIViewModel model, OrderAPIViewModel result)
        {
            var orderService       = DependencyUtils.Resolve <IOrderService>();
            var productService     = DependencyUtils.Resolve <IProductService>();
            var orderDetailService = DependencyUtils.Resolve <IOrderDetailService>();
            var orderDetailDomain  = new OrderDetailDomain();
            //Order
            var order = model.ToEntity();

            order.OrderStatus    = status;
            order.DeliveryStatus = model.DeliveryStatus;
            order.CheckInPerson  = model.CheckInPerson;

            #region cập nhật order detail
            foreach (var odm in model.OrderDetails.ToList())
            {
                var productId   = productService.GetProductByCode(odm.ProductCode).ProductID;
                var orderdetail = odm.ToEntity();
                orderdetail.ProductID = productId;
                orderdetail.StoreId   = model.StoreID;

                //Orderdetail Promotion Mapping
                //Đối với đơn hàng từ POS thì phải finish mới có promotion (đơn hàng khác chưa biết..)
                if (model.DeliveryStatus == (int)DeliveryStatus.New &&
                    status == (int)OrderStatusEnum.Finish)
                {
                    foreach (var odpm in odm.OrderDetailPromotionMappings.ToList())
                    {
                        var mapping = odpm.ToEntity();
                        mapping.PromotionId = (new PromotionService())
                                              .GetByPromoCode(odpm.PromotionCode).PromotionID;
                        mapping.PromotionDetailId = (new PromotionDetailService())
                                                    .GetDetailByPromotionDetailCode(odpm.PromotionDetailCode).PromotionDetailID;
                        orderdetail.OrderDetailPromotionMappings.Add(mapping);
                    }
                }

                order.OrderDetails.Add(orderdetail);
            }
            #endregion

            #region map Order với Promotion
            //Đối với đơn hàng từ POS thì phải finish mới có promotion (đơn hàng khác chưa biết..)
            if (model.DeliveryStatus == (int)DeliveryStatus.New &&
                status == (int)OrderStatusEnum.Finish)
            {
                foreach (var opm in model.OrderPromotionMappings.ToList())
                {
                    var mapping = opm.ToEntity();
                    mapping.PromotionId = (new PromotionService())
                                          .GetByPromoCode(opm.PromotionCode).PromotionID;
                    mapping.PromotionDetailId = (new PromotionDetailService())
                                                .GetDetailByPromotionDetailCode(opm.PromotionDetailCode).PromotionDetailID;
                    order.OrderPromotionMappings.Add(mapping);
                }
            }
            #endregion

            #region cập nhật payment
            //Finished || Processing Order -> Save Payment
            if (status == (int)OrderStatusEnum.Finish ||
                status == (int)OrderStatusEnum.Processing)
            {
                var checkStatusMomo = false;
                //if
                foreach (var p in model.Payments.ToList())
                {
                    var payment = p.ToEntity();
                    if (payment.Type == (int)PaymentTypeEnum.MoMo)
                    {
                        checkStatusMomo = true;
                    }
                    order.Payments.Add(payment);
                }

                if (checkStatusMomo == true && (int)OrderStatusEnum.Finish == status)
                {
                    new PaymentDomain().SendMomoPaymentNotification(order);
                }

                if (status == (int)OrderStatusEnum.Finish)
                {
                    //Fix Order sent Don't Have Payment when finish
                    if (model.FinalAmount > 0)
                    {
                        if (model.FinalAmount != (model.TotalAmount - model.Discount - model.DiscountOrderDetail))
                        {
                            return(new OrderAPIViewModel
                            {
                                OrderStatus = model.OrderStatus,
                                InvoiceID = model.OrderCode,
                                DeliveryStatus = model.DeliveryStatus,
                                CheckInPerson = model.CheckInPerson,
                                //Something wrong, return old status
                            });
                        }
                        //TODO: Fix bug Miss Payment
                        if (model.Payments.Count() == 0)
                        {
                            var payment = new Payment();
                            payment.Amount   = model.FinalAmount;
                            payment.Status   = (int)OrderPaymentStatusEnum.Finish;
                            payment.Type     = model.Att1 != null ? (int)PaymentTypeEnum.MemberPayment : (int)PaymentTypeEnum.Cash;
                            payment.PayTime  = model.CheckInDate.Value;
                            payment.FCAmount = 0;
                            order.Payments.Add(payment);
                        }
                    }
                }
            }
            else
            {
                //Không lưu payment
            }
            #endregion

            #region Save Order
            var created = orderService.CreateOrder(order);

            if (created)
            {
                //Update tmpId
                orderDetailDomain.UpdateOrderDetailId(order);
                orderService.EditOrder(order);
                //Success
            }
            else
            {
                result.OrderStatus = model.OrderStatus;
                //Fail - Return old status
            }
            #endregion
            return(result);
        }
        private OrderAPIViewModel UpdateOrder(int status, Models.Entities.Order order, OrderAPIViewModel model, OrderAPIViewModel result)
        {
            var orderService       = DependencyUtils.Resolve <IOrderService>();
            var productService     = DependencyUtils.Resolve <IProductService>();
            var paymentService     = DependencyUtils.Resolve <IPaymentService>();
            var orderDetailService = DependencyUtils.Resolve <IOrderDetailService>();
            var orderDetailDomain  = new OrderDetailDomain();

            #region Đơn hàng mới sẽ cập nhật order detail và payment
            if (model.DeliveryStatus == (int)DeliveryStatus.New)
            {
                //Không được edit đơn hàng finish trên server !!!
                if (order.OrderStatus == (int)OrderStatusEnum.Finish)
                {
                    result.OrderStatus = model.OrderStatus;
                    //Return old status
                }
                #region Start to edit if this order != finished
                //Chỉ edit khi đơn hàng chưa finish trên server
                else if (order.OrderStatus != (int)OrderStatusEnum.Finish)
                {
                    var modifiedPayment     = false;
                    var modifiedOrderDetail = false;

                    #region Nếu chưa từng có orderdetail hoặc có sự thay đổi orderdetail thì sẽ xóa hết order detail
                    if (!order.OrderDetails.Any() ||
                        order.LastModifiedOrderDetail == null ||
                        (order.LastModifiedOrderDetail != null &&
                         order.LastModifiedOrderDetail != model.LastModifiedOrderDetail))
                    {
                        //Delete all orderdetail
                        var lastOdList = order.OrderDetails.ToList();
                        foreach (var od in lastOdList)
                        {
                            order.OrderDetails.Remove(od);
                            var orderDetailCurrent = orderDetailService.Get(od.OrderDetailID);
                            orderDetailService.Delete(orderDetailCurrent);
                        }
                        modifiedOrderDetail = true;
                    }
                    #endregion

                    #region Đơn hàng đang xử lý hoặc đã thành công mới cập nhật payment bằng cách củ chuối xóa hết rồi insert lại
                    if (status == (int)OrderStatusEnum.Finish ||
                        status == (int)OrderStatusEnum.Processing)
                    {
                        //Chưa từng có payment hoặc có sự thay đổi payment
                        if (!order.Payments.Any() ||
                            order.Payments.Sum(p => p.Amount) == 0 ||
                            order.LastModifiedPayment == null ||
                            (order.LastModifiedPayment != null &&
                             order.LastModifiedPayment != model.LastModifiedPayment))
                        {
                            //Delete all payment
                            var lastPList = order.Payments.ToList();
                            foreach (var p in lastPList)
                            {
                                order.Payments.Remove(p);
                                var currentpayment = paymentService.Get(p.PaymentID);
                                paymentService.Delete(currentpayment);
                            }
                            modifiedPayment = true;
                        }
                    }
                    #endregion

                    #region redload order db nếu có bất kì sự thay đổi
                    if (modifiedPayment || modifiedOrderDetail)
                    {
                        order = null;
                        order = orderService.GetOrderByInvoiceId(model.OrderCode);
                    }
                    #endregion

                    #region update if modify Payment or OrderDetail
                    if (modifiedOrderDetail)
                    {
                        //Vì có sự thay đổi orderdetail -> order có thay đổi -> update order
                        //Order
                        order = model.ToEntity();

                        //Orderdetail
                        foreach (var odm in model.OrderDetails.ToList())
                        {
                            var productId   = productService.GetProductByCode(odm.ProductCode).ProductID;
                            var orderdetail = odm.ToEntity();
                            orderdetail.ProductID = productId;
                            orderdetail.StoreId   = model.StoreID;

                            //Orderdetail Promotion Mapping
                            //Đối với đơn hàng từ POS thì phải finish mới có promotion (đơn hàng khác chưa biết..)
                            if (status == (int)OrderStatusEnum.Finish)
                            {
                                foreach (var odpm in odm.OrderDetailPromotionMappings.ToList())
                                {
                                    var mapping = odpm.ToEntity();
                                    mapping.PromotionId = (new PromotionService())
                                                          .GetByPromoCode(odpm.PromotionCode).PromotionID;
                                    mapping.PromotionDetailId = (new PromotionDetailService())
                                                                .GetDetailByPromotionDetailCode(odpm.PromotionDetailCode).PromotionDetailID;

                                    orderdetail.OrderDetailPromotionMappings.Add(mapping);
                                }
                            }

                            order.OrderDetails.Add(orderdetail);
                        }

                        //Order Promotion Mapping
                        //Đối với đơn hàng từ POS thì phải finish mới có promotion (đơn hàng khác chưa biết..)
                        if (status == (int)OrderStatusEnum.Finish)
                        {
                            foreach (var opm in model.OrderPromotionMappings.ToList())
                            {
                                var mapping = opm.ToEntity();
                                mapping.PromotionId = (new PromotionService())
                                                      .GetByPromoCode(opm.PromotionCode).PromotionID;
                                mapping.PromotionDetailId = (new PromotionDetailService())
                                                            .GetDetailByPromotionDetailCode(opm.PromotionDetailCode).PromotionDetailID;

                                order.OrderPromotionMappings.Add(mapping);
                            }
                        }
                    }

                    if (modifiedPayment)
                    {
                        //Payment
                        foreach (var p in model.Payments.ToList())
                        {
                            var payment = p.ToEntity();
                            order.Payments.Add(payment);
                        }
                    }

                    //Save
                    order.OrderStatus    = status;
                    order.DeliveryStatus = model.DeliveryStatus;
                    order.CheckInPerson  = model.CheckInPerson;
                    orderService.EditOrder(order);

                    if (modifiedOrderDetail)
                    {
                        //Update tmpId
                        orderDetailDomain.UpdateOrderDetailId(order);
                        orderService.EditOrder(order);
                    }
                    //Success
                    #endregion
                }
                #endregion
            }
            #endregion
            #region Đơn hàng cũ thì sẽ tiến hành cập nhật lại payment
            //Đơn hàng delivery
            else
            {
                //Không có sự thay đổi ở orderdetail
                #region Nếu đã hoàn thành hoặc đang xử lí sẽ cập nhật payment
                if (status == (int)OrderStatusEnum.Finish ||
                    status == (int)OrderStatusEnum.Processing)
                {
                    var modifiedPayment = false;

                    #region delete all payment in order
                    var pList = order.Payments.ToList();
                    foreach (var p in pList)
                    {
                        modifiedPayment = true;
                        order.Payments.Remove(p);
                        var paymentcurrent = paymentService.Get(p.PaymentID);
                        paymentService.Delete(paymentcurrent);
                    }
                    #endregion

                    #region redload order db if any payment is deleted
                    if (modifiedPayment)
                    {
                        order = null;
                        order = orderService.GetOrderByInvoiceId(model.OrderCode);
                    }
                    #endregion
                    var checkStatusMomo = false;

                    #region add payment from Order view model to order again. Check if there is any Momo payment
                    foreach (var p in model.Payments.ToList())
                    {
                        var payment = p.ToEntity();
                        if (payment.Type == (int)PaymentTypeEnum.MoMo)
                        {
                            checkStatusMomo = true;
                        }
                        order.Payments.Add(payment);
                    }
                    #endregion

                    //for Order payed by Momo
                    if (checkStatusMomo && status == (int)OrderStatusEnum.Finish)
                    {
                        new PaymentDomain().SendMomoPaymentNotification(order);
                        ////update
                        //Fix Order sent Don't Have Payment when finish
                        if (model.FinalAmount > 0)
                        {
                            if (model.FinalAmount != (model.TotalAmount - model.Discount - model.DiscountOrderDetail))
                            {
                                return(new OrderAPIViewModel
                                {
                                    OrderStatus = model.OrderStatus,
                                    InvoiceID = model.OrderCode,
                                    DeliveryStatus = model.DeliveryStatus,
                                    CheckInPerson = model.CheckInPerson,
                                    //Something wrong, return old status
                                });
                            }
                            //TODO: Fix bug Miss Payment
                            if (model.Payments.Count() == 0)
                            {
                                var payment = new Payment();
                                payment.Amount   = model.FinalAmount;
                                payment.Status   = (int)OrderPaymentStatusEnum.Finish;
                                payment.Type     = model.Att1 != null ? (int)PaymentTypeEnum.MemberPayment : (int)PaymentTypeEnum.Cash;
                                payment.PayTime  = model.CheckInDate.Value;
                                payment.FCAmount = 0;
                                order.Payments.Add(payment);
                            }
                        }
                    }

                    order.OrderStatus    = status;
                    order.DeliveryStatus = model.DeliveryStatus;
                    order.CheckInPerson  = model.CheckInPerson;
                    orderService.EditOrder(order);
                    //Success
                }
                #endregion
                #region if status = pre cancel
                else if (status == (int)OrderStatusEnum.PreCancel)
                {
                    order.OrderStatus    = status;
                    order.DeliveryStatus = model.DeliveryStatus;
                    order.CheckInPerson  = model.CheckInPerson;
                    orderService.EditOrder(order);
                }
                #endregion
                else
                //Không có gì cập nhật
                {
                    result.OrderStatus = model.OrderStatus;
                    //Return old status
                }
            }
            #endregion
            return(result);
        }