public static void SuggestCheckoutLocations(int userId)
        {
            using (TransactionScope tran = TransactionScopeFactory.CreateTransactionScope())
            {
                CheckoutDataContextProvider dcp = CheckoutDataContextProvider.Instance;

                // Adım 1: İptal edilmemiş ve durumu LocationWaiting olan sipariş kalemleri çekilir
                List<OrderItem> locationWaitingItemList = CheckoutBL.GetLocationWaitingItemList(dcp);

                if (locationWaitingItemList == null || locationWaitingItemList.Count <= 0)
                    return;

                List<string> variantCodeList = locationWaitingItemList.Select(x => x.VariantCode).Distinct().ToList();

                // Adım 2: Sipariş kalemlerinin varyant kodları ile birlikte (barkod değil) müşteri servisine gidilir
                List<VariantStoreStock> incomingStoreStockList = BeymenStockServiceWrapper.GetBeymenVariantStoreStockList(variantCodeList);

                //log için
                VariantStoreStock[] copyOfIncomingStockList = new VariantStoreStock[incomingStoreStockList.Count];
                incomingStoreStockList.CopyTo(copyOfIncomingStockList);
                List<VariantStoreStock> stockCopyList = copyOfIncomingStockList.ToList();

                // Adım 3: Müşteri erp sistemine hala bildirilmemiş sipariş kalemleri var ise gelen stoktan düşülür
                incomingStoreStockList = RecalculateStockByExcludingUsed(incomingStoreStockList);

                List<LocationDO> allCollectionLocations = LocationBL.GetAllCollectionLocation();
                List<Order> orderListOfItems = CheckoutBL.GetOrderListByIDList(locationWaitingItemList.Select(x => x.OrderID).ToList());
                List<OrderItem> orderItemListOfOrders = CheckoutBL.GetAllOrderItemsOfOrders(orderListOfItems.Select(x => x.ID).ToList());

                // Adım 4: Önceden toplama merkezi atanmış ancak hala LocationWaiting durumunda olan sipariş kalemleri ayrıca tespit edilir.
                var previouslyNotFoundLocationVariantList = (from i in locationWaitingItemList
                                                             where i.CollectionLocationID.HasValue && LocationBL.IsLocationAvailable(i.CollectionLocationID)
                                                             group i by i.VariantCode into g
                                                             select new
                                                             {
                                                                 VariantCode = g.Key,
                                                                 Location = allCollectionLocations.Where(x => g.Select(c => c.CollectionLocationID.Value)
                                                                                                             .Distinct()
                                                                                                             .ToList()
                                                                                                             .Contains(x.ID))
                                                                                                    .OrderByDescending(o => o.Priority)
                                                                                                    .FirstOrDefault()
                                                             }).ToList();

                // Adım 5: Bekleyen sipariş kalemlerine lokasyon atanmaya başlar
                StringBuilder builder = new StringBuilder();
                foreach (OrderItem item in locationWaitingItemList)
                {
                    // Adım 6: Eğer sipariş kalemine ait bir sipariş yoksa pas geçer
                    Order orderOfItem = orderListOfItems.FirstOrDefault(x => x.ID == item.OrderID);
                    if (orderOfItem == null)
                    {
                        item.LocationSuggestionProblemText = "Bu ürüne ait bir sipariş bulunamadı. Lokasyon önermek gereksiz.";
                        continue;
                    }

                    List<VariantStoreStock> variantStoreStockList = new List<VariantStoreStock>();

                    // Adım 7: Tüm lokasyonlar arasından sadece stok sorgusunda gelen lokasyonlar ve öncelik sıraları geçilir
                    foreach (var variantStoreStock in incomingStoreStockList)
                    {
                        LocationDO loc = allCollectionLocations.Where(x => x.StoreID == orderOfItem.StoreID).FirstOrDefault(l => l.Code == variantStoreStock.LocationCode);
                        if (loc != null)
                        {
                            variantStoreStock.Priority = loc.Priority;
                            variantStoreStock.LocationID = loc.ID;
                            variantStoreStockList.Add(variantStoreStock);
                        }
                        else
                        {
                            // gelen stok bilgisinin lokasyonu bizde kayıtlı değilse işleme almıyoruz.
                            continue;
                        }
                    }
                    builder.Append(Environment.NewLine);
                    builder.Append("OrderItem: " + item.ID + " VariantCode: " + item.VariantCode);

                    // Adım 8: Varyant kodunun tespit edilen lokasyonlarda olup olmadığına bakılır
                    List<VariantStoreStock> stockListOfOrderItem = variantStoreStockList.Where(x => x.VariantCode == item.VariantCode).ToList();
                    if (stockListOfOrderItem.Count == 0)
                    {
                        item.LocationSuggestionProblemText = "Bu ürün sistemde tanımlı lokasyonların hiçbirinde bulunamadı.";
                        builder.Append("Lokasyon Bulunamadı!");
                        log.Info(builder.ToString());
                        builder.Clear();
                        continue;
                    }

                    List<LocationDO> locationListOfItem = allCollectionLocations.Where(x => stockListOfOrderItem.Select(s => s.LocationCode).Contains(x.Code) && x.StoreID == orderOfItem.StoreID).ToList();

                    if (locationListOfItem.Count == 0)
                    {
                        item.LocationSuggestionProblemText = "Beymende'ki lokasyonlar ile uyuşmazlık var. Lokasyon veritabanı eski kalmış olabilir.";
                        builder.Append("Lokasyon Uyuşmazlığı!");
                        log.Info(builder.ToString());
                        builder.Clear();
                        continue;
                    }

                    stockListOfOrderItem = stockListOfOrderItem.Where(x => locationListOfItem.Select(l => l.Code).Contains(x.LocationCode)).ToList();

                    builder.Append(Environment.NewLine);
                    foreach (var variantStoreStock in stockListOfOrderItem)
                    {
                        builder.Append("Lokasyon: " + variantStoreStock.LocationCode + ", Stok: " + variantStoreStock.Stock);
                        builder.Append(Environment.NewLine);
                        VariantStoreStock beymenStock = stockCopyList.FirstOrDefault(x => x.LocationCode == variantStoreStock.LocationCode && x.VariantCode == variantStoreStock.VariantCode);
                        if (beymenStock != null)
                        {
                            builder.Append("Beymen Lokasyon: " + beymenStock.LocationCode + "Beymen Stok: " + beymenStock.Stock);
                            builder.Append(Environment.NewLine);
                        }
                    }

                    // Önceden toplama merkezi atanmış ancak hala LocationWaiting durumunda olan sipariş kalemlerine farklı bir lokasyon önerisi yapılabilir mi diye kontrol ediliyor
                    // yapılamıyorsa önceden atanmış toplama merkezi bilgisini temizliyor.
                    var previouslyNotFoundLocationOfItem = previouslyNotFoundLocationVariantList.FirstOrDefault(x => x.VariantCode == item.VariantCode);
                    if (previouslyNotFoundLocationOfItem != null)
                    {
                        locationListOfItem = locationListOfItem.Where(x => x.Priority > previouslyNotFoundLocationOfItem.Location.Priority).OrderBy(x => x.Priority).ToList();
                        stockListOfOrderItem = stockListOfOrderItem.Where(x => locationListOfItem.Select(l => l.Code).Contains(x.LocationCode)).ToList();

                        if (stockListOfOrderItem.Count == 0)
                        {
                            item.LocationSuggestionProblemText = "Daha önce bulunamayan lokasyon(lar)dan başka bir lokasyon önerilmedi.";
                            item.CollectionLocationID = null;
                            item.StatusCode = OrderItemStatus.LocationWaiting.ToString();
                            item.StatusCodeUpdateTime = DateTime.UtcNow;

                            builder.Append("Daha Önce Bulunamayan Lokasyonlar önerildi!");
                            log.Info(builder.ToString());
                            builder.Clear();
                            continue;
                        }
                    }

                    // Sipariş kalemi için stoğun bulunup bulunamadığına bakılıyor
                    stockListOfOrderItem = stockListOfOrderItem.Where(x => x.Stock > 0).ToList();
                    if (stockListOfOrderItem.Count == 0)
                    {
                        item.LocationSuggestionProblemText = "Stok bulunamadı.";
                        item.CollectionLocationID = null;
                        item.StatusCode = OrderItemStatus.LocationWaiting.ToString();
                        item.StatusCodeUpdateTime = DateTime.UtcNow;

                        builder.Append("Stok Yok!");
                        log.Info(builder.ToString());
                        builder.Clear();
                        continue;
                    }
                    else
                    {
                        // Stoğu 2 ve daha fazla olan lokasyonlar öncelikli olarak sipariş kalemine atanıyor. Eğer 2 ve daha büyük yoksa stoğu 1 olanlar atanıyor.

                        int locationSuggestionStockThreshold = int.Parse(ConfigurationManager.AppSettings["LocationSuggestionStockThreshold"]);
                        if (stockListOfOrderItem.Any(p => p.Stock >= locationSuggestionStockThreshold))
                        {
                            stockListOfOrderItem = stockListOfOrderItem.Where(x => x.Stock >= locationSuggestionStockThreshold).ToList();

                            int topPriority = stockListOfOrderItem.Min(p => p.Priority);
                            stockListOfOrderItem = stockListOfOrderItem.Where(x => x.Priority == topPriority).ToList();
                        }
                        else
                        {
                            int topPriority = stockListOfOrderItem.Min(p => p.Priority);
                            stockListOfOrderItem = stockListOfOrderItem.Where(x => x.Priority == topPriority).ToList();
                        }

                        VariantStoreStock stockItem = stockListOfOrderItem[new Random().Next(stockListOfOrderItem.Count)];

                        stockItem.Stock -= 1;
                        item.LocationSuggestionProblemText = null;
                        item.CollectionLocationID = stockItem.LocationID;

                        List<OrderItem> orderItemsOfCurrentOrder = orderItemListOfOrders.Where(x => x.OrderID == item.OrderID).ToList();
                        SuggestPackagingLocation(item, orderOfItem, orderItemsOfCurrentOrder);
                        item.StatusCode = OrderItemStatus.CheckoutWaiting.ToString();
                        item.StatusCodeUpdateTime = DateTime.UtcNow;
                    }

                    log.Info(builder.ToString());
                    builder.Clear();
                }

                dcp.CommitChanges(userId);
                tran.Complete();
            }
        }
        public static List<VariantStoreStock> GetVariantsStoreStock(List<string> variantCodeList)
        {
            //TODO burası beymen servisinden gerçek stokları çekmeli
            //VariantCode|Store|Stock, VariantCode|Store|Stock şeklinde data gelecek büyük ihtimalle 

            //Random stok yaratma

            List<VariantStoreStock> variantStoreStocks = new List<VariantStoreStock>();
            List<string> locationList = new List<string> { /*"1175", "1137", "1141", "1174", "1183", "1194", "1207", "1196",*/ "2001"};

            var wantedVariant = variantCodeList.FirstOrDefault(x => x == "100597743003");
            if (wantedVariant != null)
            {
                return new List<VariantStoreStock>
                       {
                           new VariantStoreStock
                           {
                               LocationCode = "1026",
                               Priority = 30,
                               Stock = 1,
                               VariantCode = "100597743003"
                           },
                           new VariantStoreStock
                           {
                               LocationCode = "1137",
                               Priority = 120,
                               Stock = 1,
                               VariantCode = "100597743003"
                           },
                           new VariantStoreStock
                           {
                               LocationCode = "1141",
                               Priority = 130,
                               Stock = 1,
                               VariantCode = "100597743003"
                           }
                       };
            }

            foreach (var variantCode in variantCodeList)
            {
                foreach (var location in locationList)
                {
                    int locationProbability = Random.Next(0, 8);
                    if (locationProbability >= 6)
                    {
                        continue;
                    }

                    Random pRandom = new Random((int)DateTime.Now.Ticks);

                    int probability = pRandom.Next(0, 5);

                    if (probability > 0)
                    {
                        int stockCount = Random.Next(1, 7);

                        VariantStoreStock variantStock = new VariantStoreStock();
                        variantStock.Stock = stockCount;
                        variantStock.LocationCode = location.Trim();
                        variantStock.VariantCode = variantCode.Trim();
                        variantStoreStocks.Add(variantStock);
                    }
                }
            }

            return variantStoreStocks;
        }
        //Daha mock olanlar kullanılıyor.
        public static List<VariantStoreStock> GetBeymenVariantStoreStockList(List<string> variantCodeList)
        {
            if (EnvironmentUtils.IsDEV())
            {
                return BeymenStockServiceMock.GetVariantsStoreStock(variantCodeList);
            }
            else
            {
                List<List<string>> dividedList = variantCodeList.ToDividedList(1000);

                List<VariantStoreStock> resultList = new List<VariantStoreStock>();

                foreach (var variantList in dividedList)
                {
                    Beymen_eCommClient beymenService = new Beymen_eCommClient();
                    string storeStockList;
                    try
                    {
                        storeStockList = beymenService.StokKontrolMagaza(_siteID, _siteKey, variantList.ToArray());
                    }
                    catch (Exception e)
                    {
                        string message = "Store stock update beymenden hata aldı. Varyant kodları: " + string.Join(",", variantList);
                        ElmahLogger.Error(message, e);
                        continue;
                    }

                    try
                    {
                        if (string.IsNullOrEmpty(storeStockList))
                        {
                            continue;
                        }

                        string[] storeStockBlockData = storeStockList.Split(',');

                        if (storeStockBlockData.Any() == false)
                        {
                            continue;
                        }

                        foreach (var storeStock in storeStockBlockData)
                        {
                            string[] firstBreakdown = storeStock.Split('|');
                            if (firstBreakdown.Count() < 2)
                            {
                                continue;
                            }

                            VariantStoreStock newVariantStoreStock = new VariantStoreStock();
                            newVariantStoreStock.VariantCode = firstBreakdown[0].Trim().TrimStart('0');

                            string[] secondBreakdown = firstBreakdown[1].Split(':');
                            if (secondBreakdown.Count() < 2)
                            {
                                newVariantStoreStock.Stock = 0;
                                continue;
                            }

                            newVariantStoreStock.LocationCode = secondBreakdown[0].Trim();
                            int stock = 0;
                            int.TryParse(secondBreakdown[1], out stock);
                            newVariantStoreStock.Stock = stock;

                            resultList.Add(newVariantStoreStock);
                        }
                    }
                    catch (Exception e)
                    {
                        string message = "Beymen stock cevabının parse edilemsi sırasında hata oluştu.";
                        ElmahLogger.Error(message, e);
                    }
                }
                return resultList;
            }
        }