コード例 #1
0
        static public async Task PortCatagories()
        {
            List <ShopifySharp.CustomCollection> list = await Shopify.GetCollections();

            List <CatalogObjectBatch> batches = new List <CatalogObjectBatch>();
            CatalogObjectBatch        batch   = new CatalogObjectBatch
            {
                Objects = new List <CatalogObject>()
            };

            batches.Add(batch);

            foreach (ShopifySharp.CustomCollection collection in list)
            {
                CatalogObject category = new CatalogObject(
                    Type: "CATEGORY",
                    Id: $"#{collection.Title}",
                    PresentAtAllLocations: true,
                    CategoryData: new CatalogCategory
                {
                    Name = collection.Title
                }
                    );
                batch.Objects.Add(category);
            }
            CatalogApi api = new CatalogApi();
            BatchUpsertCatalogObjectsRequest  body     = new BatchUpsertCatalogObjectsRequest(Guid.NewGuid().ToString(), batches);
            BatchUpsertCatalogObjectsResponse response = await api.BatchUpsertCatalogObjectsAsync(body);
        }
コード例 #2
0
        private IObservable <Unit> SyncCategories(string beginTime, ISourceCache <SSBakery.Models.CatalogCategory, string> categoryCache)
        {
            var catalogApi  = new CatalogApi();
            var objectTypes = new List <SearchCatalogObjectsRequest.ObjectTypesEnum> {
                SearchCatalogObjectsRequest.ObjectTypesEnum.CATEGORY
            };
            //var beginTime = "2018-08-02T15:00:00Z";
            var request = new SearchCatalogObjectsRequest(ObjectTypes: objectTypes, IncludeDeletedObjects: true, BeginTime: beginTime);

            IObservable <CatalogObject> resultStream = catalogApi
                                                       .SearchCatalogObjectsAsync(request)
                                                       .ToObservable()
                                                       .Where(x => x.Objects != null)
                                                       .SelectMany(x => x.Objects);

            IObservable <Unit> deletedCategories = resultStream
                                                   .Where(x => x.IsDeleted.Value && categoryCache.Lookup(x.Id).HasValue)
                                                   .SelectMany(x => _categoryRepo.Delete(x.Id));

            IObservable <Unit> addedOrModifiedCategories = resultStream
                                                           .Where(x => !x.IsDeleted.Value)
                                                           .Select(x => UpdateCategoryCache(x, categoryCache))
                                                           .SelectMany(category => _categoryRepo.Upsert(category));

            return(Observable.Merge(deletedCategories, addedOrModifiedCategories));
        }
コード例 #3
0
        public void Init()
        {
            instance     = new CatalogApi();
            testAccounts = new TestAccounts();
            var testAccount = testAccounts["US-Prod"];

            Configuration.Default.AccessToken = testAccount.AccessToken;

            try
            {
                var request =
                    new BatchUpsertCatalogObjectsRequest(
                        IdempotencyKey: Guid.NewGuid().ToString(),
                        Batches: new List <CatalogObjectBatch>()
                        );
                request.Batches.Add(new CatalogObjectBatch(Objects: OBJECTS));
                var response = instance.BatchUpsertCatalogObjects(request);
                idMap = response.IdMappings.ToDictionary(
                    keySelector: m => m.ClientObjectId,
                    elementSelector: m => m.ObjectId
                    );
            }
            catch (Exception ex)
            {
                Assert.Fail("Failed to build catalog objects. {0}", ex.ToString());
            }
        }
コード例 #4
0
        static public async Task FixLocations()
        {
            CatalogApi api    = new CatalogApi();
            string     cursor = null;

            string[] types = { "MODIFIER_LIST", "ITEM", "MODIFIER", "CATEGORY", "DISCOUNT", "TAX", "ITEM_VARIATION" };
            foreach (string type in types)
            {
                List <CatalogObjectBatch> batches = new List <CatalogObjectBatch>();
                CatalogObjectBatch        batch   = new CatalogObjectBatch
                {
                    Objects = new List <CatalogObject>()
                };
                batches.Add(batch);
                do
                {
                    ListCatalogResponse resp = await api.ListCatalogAsync(cursor, type);

                    if (resp.Objects != null && resp.Objects.Count > 0)
                    {
                        batch.Objects.AddRange(resp.Objects.Where(o => o.PresentAtAllLocations == false));
                    }
                    cursor = resp.Cursor;
                } while (cursor != null);

                foreach (CatalogObject obj in batch.Objects)
                {
                    obj.PresentAtAllLocations = true;
                }
                BatchUpsertCatalogObjectsRequest  body     = new BatchUpsertCatalogObjectsRequest(Guid.NewGuid().ToString(), batches);
                BatchUpsertCatalogObjectsResponse response = await api.BatchUpsertCatalogObjectsAsync(body);
            }
        }
コード例 #5
0
        static public async Task SetInventory(List <ShopifySharp.Product> products)
        {
            CatalogApi api    = new CatalogApi();
            V1ItemsApi v1api  = new V1ItemsApi();
            string     cursor = null;

            do
            {
                ListCatalogResponse resp = await api.ListCatalogAsync(cursor, "ITEM_VARIATION");

                foreach (CatalogObject obj in resp.Objects)
                {
                    long id = long.Parse(obj.ItemVariationData.UserData);
                    ShopifySharp.Product        prod    = products.FirstOrDefault(p => p.Variants.Any(v => v.Id == id));
                    ShopifySharp.ProductVariant variant = prod.Variants.FirstOrDefault(v => v.Id == id);
                    V1AdjustInventoryRequest    body    = new V1AdjustInventoryRequest(variant.InventoryQuantity, "MANUALADJUST", "From Shopify");
                    try
                    {
                        await v1api.AdjustInventoryAsync(obj.CatalogV1Ids[0].LocationId, obj.CatalogV1Ids[0]._CatalogV1Id, body);
                    }
                    catch (Exception)
                    {
                    }
                    //				obj.PresentAtAllLocations = true;
                }

                cursor = resp.Cursor;
            } while (cursor != null);
        }
コード例 #6
0
        public SquareItemsService(SquareConfig config, SquareMerchantCredentials credentials, ISquareLocationsService locationsService) : base(config, credentials)
        {
            Condition.Requires(locationsService, "locationsService").IsNotNull();

            this._catalogApi       = new CatalogApi(base.ApiConfiguration);
            this._inventoryApi     = new InventoryApi(base.ApiConfiguration);
            this._locationsService = locationsService;
        }
コード例 #7
0
        public RestaurantFullMenu getInventory()
        {
            RestaurantFullMenu retMenu = new RestaurantFullMenu();

            Configuration.Default.AccessToken = "sq0atp-ck43ZyjwVgVq8ZnmW98QNw";
            int categorynumber = 0;

            var apiInstance = new CatalogApi();

            try
            {
                // ListCatalog
                ListCatalogResponse result = apiInstance.ListCatalog(null, null);
                IDictionary <string, RestaurantItem>     items     = new Dictionary <string, RestaurantItem>();
                IDictionary <string, RestaurantCategory> categorys = new Dictionary <string, RestaurantCategory>();

                foreach (var restObj in result.Objects)
                {
                    switch (restObj.Type)
                    {
                    case Square.Connect.Model.CatalogObject.TypeEnum.ITEM:
                        if (restObj.ItemData.CategoryId == "CC523COHULAO3I5DAZRPCNKB")
                        {
                            items.Add(restObj.ItemData.Name, new RestaurantItem()
                            {
                                ItemName        = restObj.ItemData.Name,
                                ItemDescription = restObj.ItemData.Description,
                                ItemPrice       = "$12"
                            });
                        }
                        break;

                    case Square.Connect.Model.CatalogObject.TypeEnum.CATEGORY:
                        categorynumber = categorynumber + 1;
                        categorys.Add(restObj.CategoryData.Name, new RestaurantCategory()
                        {
                            CategoryName   = restObj.CategoryData.Name,
                            CategoryNumber = categorynumber.ToString()
                        });
                        break;

                    default:
                        break;
                    }
                }

                retMenu.items     = items;
                retMenu.categorys = categorys;
            }
            catch (Exception e)
            {
                //Debug.Print("Exception when calling CatalogApi.ListCatalog: " + e.Message);
            }

            return(retMenu);
        }
コード例 #8
0
        /**
         * Constructor to take in API credentials and create the backend API client
         * Also initializes the specific API clients for each object that will be used
         *
         * user: The Zuora API username
         * pass: The Zuora API password
         */
        public ApplicationManager(String user, String pass)
        {
            //Creating the API client with the new REST endpoint
            zApi = new ApiClient("https://rest.apisandbox.zuora.com/v1");

            //Adding the username and password to the header for subsequent API calls
            zApi.AddDefaultHeader("apiAccessKeyId", user);
            zApi.AddDefaultHeader("apiSecretAccessKey", pass);

            //Initializing API clients for Product Catalog, Accounts, and Subscriptions
            catalogApi       = new CatalogApi(zApi);
            accountsApi      = new AccountsApi(zApi);
            subscriptionsApi = new SubscriptionsApi(zApi);
        }
コード例 #9
0
        static public async Task GetProductsAsync()
        {
            CatalogApi api    = new CatalogApi();
            string     cursor = null;
//			string[] types = { "ITEM_VARIATION", "MODIFIER_LIST", "ITEM", "MODIFIER", "CATEGORY", "DISCOUNT", "TAX" };
//			foreach (string type in types)
            {
                do
                {
                    ListCatalogResponse resp = await api.ListCatalogAsync(cursor, "ITEM");

                    if (resp.Objects != null && resp.Objects.Count > 0)
                    {
                    }
                    cursor = resp.Cursor;
                } while (cursor != null);
            }
        }
コード例 #10
0
        static public async Task DeleteProducts()
        {
            CatalogApi api    = new CatalogApi();
            string     cursor = null;

            string[] types = { "ITEM_VARIATION", "MODIFIER_LIST", "ITEM", "MODIFIER", "CATEGORY", "DISCOUNT", "TAX" };
            foreach (string type in types)
            {
                do
                {
                    ListCatalogResponse resp = await api.ListCatalogAsync(cursor, type);

                    if (resp.Objects != null && resp.Objects.Count > 0)
                    {
                        BatchDeleteCatalogObjectsRequest  body    = new BatchDeleteCatalogObjectsRequest(resp.Objects.Select(s => s.Id).ToList());
                        BatchDeleteCatalogObjectsResponse delResp = await api.BatchDeleteCatalogObjectsAsync(body);
                    }
                    cursor = resp.Cursor;
                } while (cursor != null);
            }
        }
コード例 #11
0
        static public async Task FixBarCodes(List <ShopifySharp.Product> products)
        {
            CatalogApi api    = new CatalogApi();
            string     cursor = null;
            List <CatalogObjectBatch> batches = new List <CatalogObjectBatch>();
            CatalogObjectBatch        batch   = new CatalogObjectBatch
            {
                Objects = new List <CatalogObject>()
            };

            batches.Add(batch);

            do
            {
                ListCatalogResponse resp = await api.ListCatalogAsync(cursor, "ITEM_VARIATION");

                if (resp.Objects != null && resp.Objects.Count > 0)
                {
                    batch.Objects.AddRange(resp.Objects);
                }
                cursor = resp.Cursor;
            } while (cursor != null);

            foreach (CatalogObject obj in batch.Objects)
            {
                long id = long.Parse(obj.ItemVariationData.UserData);
                ShopifySharp.Product        prod    = products.FirstOrDefault(p => p.Variants.Any(v => v.Id == id));
                ShopifySharp.ProductVariant variant = prod.Variants.FirstOrDefault(v => v.Id == id);

//				ShopifySharp.ProductVariant variant = products.Select(p => p.Variants.First(v => v.Id.ToString() == obj.ItemVariationData.UserData)).First();
                obj.ItemVariationData.Upc = variant.Barcode;
                obj.ItemVariationData.Sku = variant.Barcode;
//				obj.PresentAtAllLocations = true;
            }

            BatchUpsertCatalogObjectsRequest  body     = new BatchUpsertCatalogObjectsRequest(Guid.NewGuid().ToString(), batches);
            BatchUpsertCatalogObjectsResponse response = await api.BatchUpsertCatalogObjectsAsync(body);
        }
コード例 #12
0
        private IObservable <Unit> SyncItems(string beginTime)
        {
            var catalogApi  = new CatalogApi();
            var objectTypes = new List <SearchCatalogObjectsRequest.ObjectTypesEnum> {
                SearchCatalogObjectsRequest.ObjectTypesEnum.ITEM
            };
            var request = new SearchCatalogObjectsRequest(ObjectTypes: objectTypes, BeginTime: beginTime);

            IObservable <CatalogObject> resultStream = catalogApi
                                                       .SearchCatalogObjectsAsync(request)
                                                       .ToObservable()
                                                       .Where(x => x.Objects != null)
                                                       .SelectMany(x => x.Objects);

            IObservable <Unit> deletedItems = resultStream
                                              .Where(x => x.IsDeleted.Value && x.ItemData.CategoryId != null)
                                              .GroupBy(x => x.ItemData.CategoryId)
                                              .SelectMany(
                group =>
            {
                return(group
                       .Select(catalogObject => catalogObject.Id)
                       .SelectMany(itemId => _itemRepoFactory.Create(group.Key).Delete(itemId)));
            });

            IObservable <Unit> addedOrModifiedItems = resultStream
                                                      .Where(x => !x.IsDeleted.Value && x.ItemData.CategoryId != null)
                                                      .Select(MapDtoToItem)
                                                      .GroupBy(x => x.CategoryId)
                                                      .SelectMany(
                x =>
            {
                return(x
                       .SelectMany(item => _itemRepoFactory.Create(x.Key).Upsert(item)));
            });

            return(Observable.Merge(deletedItems, addedOrModifiedItems));
        }
コード例 #13
0
        static public async Task PortItemsAsync2(string locationId)
        {
            List <ShopifySharp.Product> products = await Shopify.GetProductsAsync();

            List <CatalogObjectBatch> batches = new List <CatalogObjectBatch>();
            CatalogObjectBatch        batch   = new CatalogObjectBatch
            {
                Objects = new List <CatalogObject>()
            };

            batches.Add(batch);

            CatalogObject tax = new CatalogObject(
                "TAX",
                Id: $"#salestax",
                PresentAtAllLocations: true,
                TaxData: new CatalogTax
            {
                Name = "SalesTax",
                AppliesToCustomAmounts = true,
                CalculationPhase       = "SUBTOTALPHASE",
                Enabled       = true,
                InclusionType = "ADDITIVE",
                Percentage    = "8.9"
            }
                );

            CatalogObject employee = new CatalogObject(
                Type: "DISCOUNT",
                Id: $"#employee",
                PresentAtAllLocations: true,
                DiscountData: new CatalogDiscount
            {
                Name         = "Employee",
                DiscountType = "FIXEDPERCENTAGE",
                LabelColor   = "Red",
                PinRequired  = false,
                Percentage   = "40"
            }
                );

            batch.Objects.Add(tax);
            foreach (ShopifySharp.Product prod in products)
            {
                CatalogObject obj = new CatalogObject(
                    Type: "ITEM",
                    Id: $"#{prod.Title}",
                    PresentAtAllLocations: true,
                    ItemData: new CatalogItem
                {
                    Name = prod.Title,
                    //						Description = prod.,
                    //					CategoryId = "#Beverages",
                    TaxIds = new List <string>()
                    {
                        "#salestax"
                    },
                    Variations = new List <CatalogObject>()
                }
                    );
                foreach (ShopifySharp.ProductVariant variant in prod.Variants)
                {
                    CatalogObject vari = new CatalogObject
                                         (
                        Type: "ITEMVARIATION",
                        Id: $"#{prod.Title}-{variant.Title}",
                        PresentAtAllLocations: true,
                        ItemVariationData: new CatalogItemVariation()
                    {
                        UserData       = variant.Id.ToString(),
                        Upc            = variant.Barcode,
                        ItemId         = $"#{prod.Title}",
                        Name           = variant.Title,
                        TrackInventory = true,
                        PricingType    = "FIXEDPRICING",
                        PriceMoney     = new Money(
                            Amount: variant.Price.HasValue ? ((long?)(variant.Price.Value * 100L)) : null,
                            Currency: "USD"
                            )
                    }
                                         );
                    obj.ItemData.Variations.Add(vari);
                }
                batch.Objects.Add(obj);
            }

            CatalogApi api = new CatalogApi();

            BatchUpsertCatalogObjectsRequest  body     = new BatchUpsertCatalogObjectsRequest(Guid.NewGuid().ToString(), batches);
            BatchUpsertCatalogObjectsResponse response = await api.BatchUpsertCatalogObjectsAsync(body);

            foreach (CatalogObject item in response.Objects.Where(o => o.Type == "ITEM"))
            {
                if (!string.IsNullOrEmpty(item.ItemData.Variations?[0].ItemVariationData.UserData))
                {
                    long oldId = long.Parse(item.ItemData.Variations?[0].ItemVariationData.UserData);
                    ShopifySharp.Product prod = products.FirstOrDefault(p => p.Variants.Any(v => v.Id == oldId));

                    await ImageUploader.PortImage(locationId, item.Id, prod.Images.First().Src);
                }
            }
        }
コード例 #14
0
        //
        // GET: /Search/

        public override ActionResult Index()
        {
            // make sure this is in <appSettings>
            //	  <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

            var filter = new TypeFilter(typeof(PageModelBase))
            {
                Inverse = true
            };
            var parts = CurrentItem.GetChildren(filter);
            var productResultsPart =
                parts.SelectMany(CmsFinder.FindAllDescendentsOf <ProductResultsPart>).FirstOrDefault() ??
                parts.FirstOrDefault(p => p is ProductResultsPart) as ProductResultsPart;

            var pageHasProdResultsPart = productResultsPart != null;
            var listPriceRanges        = productResultsPart != null ? productResultsPart.ListPriceRanges : string.Empty;
            var listPriceRangesNames   = Regex.Split(listPriceRanges, @"\s*,\s*").ToList();

            var query = Request["query"];
            var page  = HttpUtility.UrlEncode(Request["pg"]);
            /* can't use query param named "page" because N2 grabs it and makes a big nuisance of itself */
            var pageSize = HttpUtility.UrlEncode(Request["pageSize"]);

            if (string.IsNullOrEmpty(pageSize))
            {
                pageSize = DefaultPageSize;
            }
            var sortBy  = HttpUtility.UrlEncode(Request["sortBy"]);
            var sortDir = HttpUtility.UrlEncode(Request["sortDir"]);

            // search in commerce
            var searchOptions = SearchOptionsUtils.GetPagingOptions(page, pageSize, sortBy, sortDir);

            //var facets = JsonToFacets(Request["facetsJson"]);

            var catalogPageViewModel = new SearchPageViewModel
            {
                Title    = query,
                Products = CatalogApi.GetProductsByKeywordAsync(string.Format("{0}", query), searchOptions).Result
            };

#if false
            bool enableFacets = catalogPageViewModel.Products.ExtendedSearchResult != null &&
                                catalogPageViewModel.Products.ExtendedSearchResult.FacetFields != null &&
                                catalogPageViewModel.Products.ExtendedSearchResult.FacetFields.Length > 0;

            if (enableFacets)
            {
                catalogPageViewModel.Products.PageSize   = DefaultPageSize_3across.AsInt();
                catalogPageViewModel.Products.TotalPages = (catalogPageViewModel.Products.TotalCount / DefaultPageSize_3across.AsInt()) + 1;
                catalogPageViewModel.Products.Products   =
                    catalogPageViewModel.Products.Products.Take(catalogPageViewModel.Products.Products.Length -
                                                                1).ToArray();
            }
#endif

            if (catalogPageViewModel.Products.Product == null)
            {
                catalogPageViewModel.Products.Product = new ProductWithRanking[0];
            }


            // if facets specified, need to render page with full facets checkbox selections, but with restricted results
            // this will almost always be a cheap call, because we probably just did it moments before and cached it
#if false
            if (facets != null)
            {
                catalogPageViewModel.Facets = facets;
                var noFacetsResults = _catAdapter.SearchProduct(query, searchOptions);
                if (catalogPageViewModel.Products.ExtendedSearchResult == null)
                {
                    catalogPageViewModel.Products.ExtendedSearchResult = noFacetsResults.ExtendedSearchResult;
                }
                else if (noFacetsResults.ExtendedSearchResult != null)
                {
                    catalogPageViewModel.Products.ExtendedSearchResult.FacetFields =
                        noFacetsResults.ExtendedSearchResult.FacetFields;
                }
                else
                {
                    catalogPageViewModel.Products.ExtendedSearchResult = null;
                }
            }
#endif

            catalogPageViewModel.SetPageTitle(string.Format("{0} &ldquo;{1}&rdquo;",
                                                            Res.Catalog_CatalogSearchResultsTitle,
                                                            Server.HtmlEncode(query ?? "")));

            WebSession.Current.Set(WebSession.SearchResultSlot, catalogPageViewModel);

            // TODO - redirect to page when there's only one exact hit
            //      - highlight results in target page, e.g. via jQuery plugin

            SetPageTitleOverrideResKey("SearchResults");

            catalogPageViewModel.PageHasProdResultsPart = pageHasProdResultsPart;
            catalogPageViewModel.EnableFacets           = false;
            catalogPageViewModel.ListPriceRangeNames    = listPriceRangesNames;

            SetPageInfo(query, null, "Sales.Catalog.SearchResults");
            return(View(catalogPageViewModel));
        }
コード例 #15
0
 public void Init()
 {
     instance = new CatalogApi();
 }
コード例 #16
0
ファイル: CatalogApiTests.cs プロジェクト: SalesTim/api-sdk
 public CatalogApiTests()
 {
     instance = new CatalogApi();
 }
コード例 #17
0
        // virtual for testing only!
        protected virtual ActionResult InternalAddToCart(AddProductModel[] addProductModels, bool skipInterstitial = false, int cpeCode = 0, int scsCode = 0)
        {
            if (addProductModels != null)
            {
                var errorMessages = new List <string>();

                // put the product(s) in the cart
                foreach (var addProductModel in addProductModels)
                {
                    try
                    {
                        var cart = CartApi.AddProductToCartAsync(Convert.ToInt64(addProductModel.ProductId), Convert.ToInt32(addProductModel.Quantity),
                                                                 Convert.ToInt64(addProductModel.OfferId)).Result;
                        WebSession.Current.SetPersistentProperty(WebSession.ShoppingCartCount, cart.TotalItemsInCart.ToString(CultureInfo.InvariantCulture));
                    }
                    catch (Exception exc)
                    {
                        var tempErrorMessages   = new List <string>();
                        var shopperApiException = exc as ShopperApiException;
                        if (shopperApiException != null)
                        {
                            switch (shopperApiException.ShopperApiError.Code)
                            {
                            case "inventory-unavailable-error":
                                tempErrorMessages.Add(Res.ShoppingCart_AddProductOutOfStock);
                                break;

                            default:
                                tempErrorMessages.Add(Res.ShoppingCart_AddProductFailed);
                                break;
                            }
                        }
                        else
                        {
                            tempErrorMessages.Add(Res.ShoppingCart_AddProductFailed);
                        }
                        errorMessages.AddRange(tempErrorMessages);
                    }
                }
                if (errorMessages.Any())
                {
                    var model = ShoppingCartViewModelBuilder.GetShoppingCartViewModelAsync().Result;
                    model.ErrorMessages = errorMessages.ToArray();
                    WebSessionSet(WebSession.ShoppingCartSlot, model);
                    return(Index());
                }

                if (addProductModels.Length == 1 && !skipInterstitial)
                {
                    var productId        = int.Parse(addProductModels[0].ProductId);
                    var interstitialLink = LinkGenerator.GenerateInterstitialLink(productId);
                    if (!String.IsNullOrEmpty(interstitialLink))
                    {
                        return(Redirect(interstitialLink));
                    }

                    var siteRoot = CmsFinder.FindSitePageFromSiteId(WebSession.Current.SiteId);
                    if (siteRoot != null && !String.IsNullOrEmpty(siteRoot.PromotionId))
                    {
                        var offers = OffersViewModelBuilder.GetCrossSellViewModelAsync(siteRoot.PromotionId,
                                                                                       CatalogApi.GetProductUri(productId), LinkGenerator.GenerateShoppingCartLink()).Result;
                        if (offers != null && offers.Offers.Count > 0)
                        {
                            interstitialLink = LinkGenerator.GenerateInterstitialLink();
                            if (!String.IsNullOrEmpty(interstitialLink))
                            {
                                return(Redirect(interstitialLink + "/" + productId));
                            }
                        }
                    }
                }
            }
            var cartLink = LinkGenerator.GenerateShoppingCartLink();

            if (scsCode != 0)
            {
                cartLink +=
                    (cartLink.LastIndexOf('?') == -1 ? "?" : "&") + ParamScsErrorCode + "=" + scsCode;
            }
            return(Redirect(cartLink));
        }