protected override string GetCatalog() { string result = "\n" + CatalogFilename + ": "; ProgressText += result + "Extracting from web service..."; var stopWatch = new StopWatch(true); var products = new List<ProductRecord>(); //Note: the following attempts at getting custom results did not return category ids // only the generic request was able to get the ids // downside is that the generic request does not get all fields, so we have to make a second request per item to get missing fields //string query = "EDI_Name=Generic\\Products&SELECT_Columns=p.HideProduct,p.IsChildOfProductCode,p.ProductCode,p.ProductID,p.ProductName,p.ProductPopularity,p.StockStatus,p.ProductUrl,p.PhotoUrl,pe.Hide_When_OutOfStock,pe.ProductCategory,pe.ProductManufacturer,pe.PhotoURL_Small,pe.ProductPrice,pe.SalePrice,pe.UPC_code,pe.Google_Gender"; //string query = "EDI_Name=Generic\\Products&SELECT_Columns=*"; string query = null; try { GetCatalogXml(query); } catch (Exception ex) { result += ex.Message; if (ex.InnerException != null) result += Environment.NewLine + ex.InnerException.Message; return result; } int numItems = (m_catalogXml == null)? 0 : m_catalogXml.Count(); if (numItems == 0) { result += "There are no products in the catalog."; return result; } ProgressText += string.Format("completed ({0}){1}Parsing Product Catalog ({2} rows)...", stopWatch.Lap(), Environment.NewLine, numItems); string tempDisplay = ProgressText; //any extra fields not in the standard export will need to be requested from the API for each product string extraFields = "p.Photos_Cloned_From,p.IsChildOfProductCode"; //special cases needed to find images and remove children List<string> extraFieldList = GetRuleFields(); if (extraFieldList.Count > 0) { //use the first product to find standard attributes and remove them from the list extraFieldList = extraFieldList.Where(x => (m_catalogXml.First().Descendants().Where( y => y.Name.LocalName.Equals(x, StringComparison.CurrentCultureIgnoreCase) ).DefaultIfEmpty(null).Single() == null)).ToList<string>(); if (extraFieldList.Count > 0) extraFields += ",pe." + extraFieldList.Aggregate((w, j) => string.Format("{0},pe.{1}", w, j)); //Note: Currently assuming that all fields are in pe table --true so far //An option would be to compile local lists of fields in each Volusion table and check against the lists //but then we may have to adjust for different version of Volusion } //create new replacement list in case child items are found m_replacementList = new List<ReplacementRecord>(); int rows = 0; foreach (var product in m_catalogXml) { var p = new ProductRecord { ProductId = Client.GetValue(product, "ProductCode"), Name = Client.GetValue(product, "ProductName"), Att2Id = string.Empty, Price = Client.GetValue(product, "ProductPrice"), SalePrice = Client.GetValue(product, "SalePrice"), Filter = string.Empty }; #if DEBUG string[] testProducts = { "calerachard10-w", "varnerfoxglovechard10-w", "mountedenchardwolff08-w", "viticciobere2008-w" }; bool testFlag = false; if (testProducts.Contains(p.ProductId)) testFlag = true; #endif if (m_secondAttEnabled) p.Att2Id = Client.GetValue(product, "ProductManufacturer"); p.Link = string.Format("{0}/ProductDetails.asp?ProductCode={1}", "http://" + m_storeShortUrl, p.ProductId); //pdp link is never https p.Rating = Client.GetValue(product, "ProductPopularity"); p.StandardCode = Client.GetValue(product, "UPC_code"); if (p.StandardCode.Length < 1) p.StandardCode = p.ProductId; var categories = product.Descendants().Where(x => x.Name.LocalName.Equals("Categories", StringComparison.CurrentCultureIgnoreCase)).SingleOrDefault(); if(categories != null) p.Att1Id = categories.Descendants("Category").Aggregate(string.Empty, (current, cat) => current + string.Format("{0},", cat.Descendants().Where(x => x.Name.LocalName.Equals("CategoryID")).Select(x => x.Value).DefaultIfEmpty("").Single())).TrimEnd(','); else p.Att1Id = Client.GetValue(product, "CategoryIDs"); //If extra fields not in the current export are required, call api to get the missing fields if (extraFields.Length > 0) { try { query = string.Format("API_Name=Generic\\Products&SELECT_Columns={0}&WHERE_Column=p.ProductCode&WHERE_Value={1}", extraFields, p.ProductId); XDocument extraXml = QueryVolusionApi(query); if ((extraXml != null) && (extraXml.Root != null)) { IEnumerable<XElement> ix = extraXml.Root.Elements("Products"); if (ix != null) //remove any repetitive fields such as the product code product.Add(ix.Descendants().Where(x => Client.GetValue(product, x.Name.ToString()).Length < 1)); } } catch { } } //check to make sure this isn't a child string parentID = Client.GetValue(product, "IsChildOfProductCode"); if ((parentID.Length > 0) && !parentID.Equals(p.ProductId)) //child so add to replacements m_replacementList.Add(new ReplacementRecord { OldId = p.ProductId, NewId = parentID }); //get the image link p.ImageLink = string.Empty; string imageID = Client.GetValue(product,"Photos_Cloned_From"); #if DEBUG if (imageID.Length > 0) // cloned image found! p.ImageLink = string.Empty; //just something to put a breakpoint on #endif if (imageID.Length < 1) //not using cloned image { //try to pull image from dtabase fields (these appear to never have the image) imageID = p.ProductId; p.ImageLink = Client.GetValue(product, "PhotoURL_Small"); if (p.ImageLink.Length < 1) p.ImageLink = Client.GetValue(product, "PhotoURL"); } if (p.ImageLink.Length < 1) //build the image link from the imageID { //replace illegal characters string encodedID = imageID.Replace("/", "-fslash-").Replace(" ", "%20"); p.ImageLink = string.Format("{0}{1}-1.jpg", m_photoBaseUrl, encodedID); } //check category conditions, exclusions, and filters ApplyRules(ref p, product); products.Add(p); ProgressText = string.Format("{0}{1} rows completed ({2})", tempDisplay, ++rows, stopWatch.Lap()); } ProgressText = string.Format("{0}Completed ({1}){2}Uploading to server...", tempDisplay, stopWatch.Lap(), Environment.NewLine); result += m_boostService.WriteTable(m_alias, CatalogFilename, products); ProgressText = string.Format("{0}({1})", result, stopWatch.Stop()); return result; }
protected override string GetCatalog() { string result = "\n" + CatalogFilename + ": "; string tempDisplay = ProgressText; ProgressText += result + "Exporting catalog..."; StopWatch exportWatch = new StopWatch(true); Mage_Api_Model_Server_V2_HandlerPortTypeClient Mclient = new Mage_Api_Model_Server_V2_HandlerPortTypeClient(); string MsessionId = ""; //---------------------CATALOG EXPORT---------------------------- //errors caught by calling function //login MsessionId = Mclient.login(m_apiUserName, m_apiKey); //Set product attributes to fetch catalogProductRequestAttributes prodAttributes = new catalogProductRequestAttributes(); string[] attributes = { "sku", "url_key", "price", "special_price", "special_from_date", "special_to_date", "parent_item_id" }; prodAttributes.attributes = attributes; //loop through all products to build the list var products = new List<ProductRecord>(); catalogProductEntity[] plist; Mclient.catalogProductList(out plist, MsessionId, null, ""); int maxCid = 0; foreach (catalogProductEntity product in plist) { var p = new ProductRecord { ProductId = product.product_id, Name = product.name, }; p.Att1Id = ""; bool first = true; foreach (string cid in product.category_ids) { if (first) first = false; else p.Att1Id += ","; p.Att1Id += cid; int id = Convert.ToInt32(cid); if (id > maxCid) maxCid = id; } p.Att2Id = ""; catalogProductReturnEntity pinfo = Mclient.catalogProductInfo(MsessionId, p.ProductId, "", prodAttributes, "id"); p.Price = pinfo.price; ; if ((pinfo.special_from_date != null) && (pinfo.special_to_date != null)) { DateTime saleStart = DateTime.Parse(pinfo.special_from_date); DateTime saleEnd = DateTime.Parse(pinfo.special_to_date); DateTime now = DateTime.Now; if (now >= saleStart && now <= saleEnd) p.Price = pinfo.special_price; } p.Filter = ""; p.Link = pinfo.url_key; p.ImageLink = ""; catalogProductImageEntity[] pimageinfo = null; try { pimageinfo = Mclient.catalogProductAttributeMediaList(MsessionId, pinfo.sku, "default", null); } catch { } if ((pimageinfo != null) && (pimageinfo.Length > 0)) p.ImageLink = pimageinfo[0].url; else { p.ImageLink = string.Format(m_thumbnailFormat, pinfo.sku); } p.StandardCode = pinfo.sku; } ProgressText = tempDisplay + string.Format("Completed ({0}){1}Uploading to server...", exportWatch.Lap(), Environment.NewLine); var sb = new StringBuilder(CommonHeader + ProductRecord.Header()); foreach (var product in products) { sb.Append(string.Format("{0}\t", product.ProductId)); sb.Append(string.Format("{0}\t", product.Name)); sb.Append(string.Format("{0}\t", product.Att1Id)); sb.Append(string.Format("{0}\t", product.Att2Id)); sb.Append(string.Format("{0}\t", product.Price)); sb.Append(string.Format("{0}\t", product.SalePrice)); sb.Append(string.Format("{0}\t", product.Rating)); sb.Append(string.Format("{0}\t", product.Filter)); sb.Append(string.Format("{0}\t", product.Link)); sb.Append(string.Format("{0}\t", product.ImageLink)); sb.Append(string.Format("{0}\r\n", product.StandardCode)); } result += m_boostService.WriteTable(m_alias, CatalogFilename, sb); //get cat info result += "\n" + Att1Filename + ": "; ProgressText = tempDisplay + result + "Exporting category names..."; catalogCategoryInfo cinfo; StringBuilder csb = new StringBuilder(CommonHeader + AttributeRecord.Header()); for (int cid = 1; cid <= maxCid; cid++) { try { cinfo = Mclient.catalogCategoryInfo(MsessionId, cid, "", null); csb.Append(cid.ToString() + "\t" + cinfo.name + "\r\n"); } catch { csb.Append(cid.ToString() + "\t" + cid.ToString() + "\r\n"); } } result += m_boostService.WriteTable(m_alias, Att1Filename, csb); ProgressText = tempDisplay + result; return result; }
protected override string GetCatalog() { string result = "\n" + CatalogFilename + ": "; ProgressText += result + "Rows to export..."; var pdWatch = new StopWatch(true); //Query 3dCart for the data //Note: Can't query for it all at once (times out on server) //See how many rows there are int targetRows = 0; string sqlQuery = "SELECT COUNT(*) FROM products"; IEnumerable<XElement> queryResults = Get3dCartQuery(sqlQuery); if (queryResults == null) { result += "(no data)"; ProgressText = result; return result; } var child = queryResults.First<XElement>(); var rowsXml = child.Element("Expr1000") ?? child.Element("field0"); if (rowsXml != null) targetRows = Convert.ToInt32(rowsXml.Value); queryResults = null; ProgressText += targetRows.ToString(); ProgressText += " (" + pdWatch.Lap() + ")"; string tempDisplay1 = ProgressText + "\nProduct/Category pairs..."; pdWatch.Start(); //restart to time cat export //Get all product/category pairs ProgressText += "\nRetrieving Product/Category pairs..."; string tempDisplay2 = ProgressText; //need to step through category list in chunks since there may be a very large number IEnumerable<XElement> catResults = null; int catRows = 0; string catID = "0"; while (true) { string categorySql = "SELECT TOP 5000 pc.catalogid, pc.categoryid\n" + "FROM product_category AS pc\n" + "WHERE pc.catalogid > " + catID + "\n" + "ORDER BY pc.catalogid"; queryResults = Get3dCartQuery(categorySql); if (queryResults == null) break; //no more data int tempCount = queryResults.Count(); if (tempCount > 0) { catResults = catResults == null ? queryResults : catResults.Concat(queryResults); //get the last cat ID from this query so next query can start there XElement x = queryResults.ElementAt(tempCount - 1); catID = Client.GetValue(x, "catalogid"); //update count catRows = catResults.Count(); ProgressText = tempDisplay2 + catRows.ToString(); pdWatch.Lap(); ProgressText += " (" + pdWatch.TotalTime + ")"; } if (tempCount < 5000) break; //all rows found } ProgressText = tempDisplay1 + catRows.ToString(); ProgressText += " (" + pdWatch.TotalTime + ")"; tempDisplay1 = ProgressText + "\nRows Exported..."; ProgressText += "\nExporting..."; pdWatch.Start(); //restart to time row export var products = new List<ProductRecord>(); int exportedRows = 0; int categorizedRows = 0; int lastId = 0; int errors = 0; bool hasResults = false; char[] illegalChars = { '\r', '\n'}; //list any illegal characters for the product name here //compile the list of fields that need to be extracted for each item in the catalog var fields = new List<string>() { "catalogid", "name", "price", "saleprice", "review_average", "onsale", "eproduct_serial", m_imageField }; if (m_secondAttEnabled) fields.Add(m_secondAttField); List<string> extraFields = GetRuleFields(); if (extraFields.Count > 0) fields = fields.Union(extraFields).Distinct().ToList(); //Loop through catalog grabbing 5000 items at a time from 3dCart string sqlQueryStart = "SELECT TOP 5000 p." + fields.Aggregate((w, j) => string.Format("{0}, p.{1}", w, j)); sqlQueryStart += "\nFROM products AS p\n"; while (true) { sqlQuery = sqlQueryStart + "WHERE p.catalogid > " + lastId.ToString() + "\n" + "ORDER BY p.catalogid"; queryResults = Get3dCartQuery(sqlQuery); if (queryResults == null) break; //no more data exportedRows += queryResults.Count(); pdWatch.Lap(); ProgressText = tempDisplay1 + exportedRows.ToString(); tempDisplay2 = ProgressText; ProgressText += " (" + pdWatch.TotalTime + ")"; string productID = ""; foreach (XElement product in queryResults) { categorizedRows++; productID = Client.GetValue(product, "catalogid"); string name = RemoveIllegalChars(Client.GetValue(product, "name"), illegalChars); try { var p = new ProductRecord { Name = name, ProductId = productID, Link = "product.asp?itemid=" + productID, ImageLink = string.Empty, Att1Id = string.Empty, Att2Id = string.Empty, Price = Client.GetValue(product, "price"), SalePrice = string.Empty, Filter = string.Empty, Rating = Client.GetValue(product, "review_average"), StandardCode = Client.GetValue(product, "eproduct_serial"), }; //create image link string thumb = Client.GetValue(product, m_imageField); if (thumb.Length > 0) { int doublehash = thumb.IndexOf("//"); if (doublehash >= 0) //thumb contains full url p.ImageLink = thumb.Substring(doublehash); //drop http protocol if present else //thumb contains asset location { p.ImageLink = "thumbnail.asp?file="; if (!thumb.StartsWith("/")) p.ImageLink += "/"; p.ImageLink += thumb; } } else //no thumbnail found so try using product id p.ImageLink = "thumbnail.asp?file=/assets/images/" + p.ProductId + ".jpg"; //need to query product_category table for each product to get it's list of categories //Note: these are all retrieved in advance in an XElement so we don't call 3dCart 30K times for this if (catResults != null) { List<string> catList = catResults.Where(x => Client.GetValue(x, "catalogid").Equals(productID)).Select(y => Client.GetValue(y, "categoryid")).ToList(); p.Att1Id += catList.Aggregate((w, j) => string.Format("{0},{1}", w, j)); } if (m_secondAttEnabled) p.Att2Id = Client.GetValue(product, m_secondAttField); bool onsale = Client.GetValue(product, "onsale").Equals("1"); if (onsale) p.SalePrice = Client.GetValue(product, "saleprice"); //call base class to check category conditions, exclusions, and filters ApplyRules(ref p, product); products.Add(p); } catch { errors++; } ProgressText = string.Format("{0} {1} completed, {2} errors ({3})", tempDisplay2, categorizedRows, errors, pdWatch.Lap()); } lastId = Convert.ToInt32(productID); hasResults = true; if (categorizedRows == targetRows) break; //read all products } if (products.Count < 1) return result + "(no data)"; var pCount = string.Format("({0} items) ", products.Count); ProgressText = string.Format("{0}{1}completed ({2}){3}Uploading to server...", tempDisplay2, pCount, pdWatch.Lap(), Environment.NewLine); result += pCount + m_boostService.WriteTable(m_alias, CatalogFilename, products); return result; }
protected override string GetCatalog() { string result = "\n" + CatalogFilename + ": "; ProgressText += result + "Extracting..."; var stopWatch = new StopWatch(true); var products = new List<ProductRecord>(); IEnumerable<XElement> items = Catalog.Elements("Product_Add"); int numItems = (items == null) ? 0 : items.Count(); if (numItems == 0) { result += " (no data)"; ProgressText = result; return result; } IEnumerable<XElement> customFields = Catalog.Elements("Product_CustomField"); IEnumerable<XElement> catAssignments = Catalog.Elements("CategoryProduct_Assign"); result += string.Format("({0} items) ", numItems); ProgressText += result + string.Format("Extracting...completed ({0}){1}Parsing Product Catalog...", stopWatch.Lap(), Environment.NewLine); string tempDisplay = ProgressText; int rows = 0, errors = 0; foreach (var product in items) { try { var p = new ProductRecord { ProductId = Client.GetValue(product, "Code"), Name = Client.GetValue(product, "Name"), Att1Id = string.Empty, Att2Id = string.Empty, Price = Client.GetValue(product, "Price"), SalePrice = string.Empty, Filter = string.Empty, ImageLink = Client.GetValue(product, "ThumbnailImage"), }; if (p.ImageLink.Length < 1) p.ImageLink = Client.GetValue(product, "FullSizeImage"); p.Link = string.Format("{0}/product/{1}.html", "http://" + m_storeShortUrl, p.ProductId); //pdp link is never https p.Rating = string.Empty; //parse custom fields IEnumerable<XElement> cfSubset = customFields.Where(x => Client.GetAttribute(x, "product").Equals(p.ProductId)); p.StandardCode = cfSubset.Where(x => Client.GetAttribute(x, "field").Equals("UPC")).Select(x => x.Value).DefaultIfEmpty(string.Empty).Single(); if (p.StandardCode.Length < 1) p.StandardCode = p.ProductId; p.Att2Id = cfSubset.Where(x => Client.GetAttribute(x, "field").Equals("brand")).Select(x => x.Value).DefaultIfEmpty(string.Empty).Single(); //get category list var categories = catAssignments.Where(x => Client.GetAttribute(x, "product_code").Equals(p.ProductId)).Select(x => Client.GetAttribute(x, "category_code")); if (categories != null) //{ // bool first = true; // foreach (string id in categories) // { // if (first) first = false; // else p.Attr1 += ","; // p.Attr1 += id; // } //} // p.Attr1 = categories.Aggregate(string.Empty, (current, cat) => current + string.Format("{0},", cat.Descendants().Where(x => x.Name.LocalName.Equals("CategoryID")).Select(x => x.Value).DefaultIfEmpty("").Single())).TrimEnd(','); p.Att1Id = categories.Aggregate((w, j) => string.Format("{0},{1}", w, j)); //check category conditions, exclusions and filters ApplyRules(ref p, product); products.Add(p); //This is now handled in ApplyRules ////Need to take care of exclusions here since we have access to all the product attributes ////if (Client.GetValue(product, "Active").Equals("No")) //// m_catConditions.AddExcludedItem(p.ProductId); //if (m_exclusions != null) //{ // foreach (var c in m_exclusions) // { // string value = Client.GetValue(product, c.FieldName); // if (value.Length < 1) //not found so check custom fields // value = cfSubset.Where(x => Client.GetAttribute(x, "field").Equals(c.FieldName)).Select(x => x.Value).DefaultIfEmpty(string.Empty).Single(); // if (value.Length > 0) // if (c.Compare(value)) // { // m_catConditions.AddExcludedItem(p.ProductId); // break; // } // } //} } catch { errors++; } ProgressText = string.Format("{0}{1} products, {2} errors ({3})", tempDisplay, ++rows, errors, stopWatch.Lap()); } ProgressText = string.Format("{0}Completed ({1}){2}Uploading to server...", tempDisplay, stopWatch.Lap(), Environment.NewLine); result += m_boostService.WriteTable(m_alias, CatalogFilename, products); stopWatch.Stop(); return result; }
protected void ApplyRules(ref ProductRecord p, XElement product) { //first check for excluded categories if (m_catConditions.AnyExcluded(p.Att1Id)) m_catConditions.AddExcludedItem(p.ProductId); else //then check all other exclusion rules { if (m_exclusions != null) { if (m_exclusions.Any(c => c.Compare(Client.GetValue(product, c.FieldName)))) m_catConditions.AddExcludedItem(p.ProductId); //add to cat excluded items so it will be prepolulated for GetExclusions } } //remove ignored categories p.Att1Id = m_catConditions.RemoveIgnored(p.Att1Id); //apply filters if (m_filtersEnabled) { if (m_catConditions.AnyUniversal(p.Att1Id)) p.Filter = m_universalFilterName; string filters = m_catConditions.AnyFiltered(p.Att1Id); if (filters.Length > 0) { if (p.Filter.Length > 0) p.Filter += ","; p.Filter += filters; } if (m_filters != null) { //bool firstItem = p.Filter.Length < 1; //foreach (Condition c in m_filters.Where(c => c.Compare(Client.GetValue(product, c.FieldName)))) //{ // if (firstItem) firstItem = false; // else p.Filter += ","; // p.Filter += c.Name; //} p.Filter += m_filters.Where( c => c.Compare(Client.GetValue(product, c.FieldName)) ).Select( c => c.Name ).Aggregate((w, j) => string.Format("{0},{1}", w, j)); } if (p.Filter.Length < 1) //if no matches then assume universal p.Filter = m_universalFilterName; } //check for full catalog replacement if (m_replacements != null && m_replacements[0].Type.Equals(ReplacementCondition.RepType.Catalog)) { var oldId = Client.GetValue(product, m_replacements[0].OldName); var newId = Client.GetValue(product, m_replacements[0].NewName); if (!m_repRecords.Any(r => r.OldId.Equals(oldId))) //can only have one replacement for each item m_repRecords.Add(new ReplacementRecord { OldId = oldId, NewId = newId }); } //check for manual recs if (m_manualCrossSell.Enabled) m_manualCrossSell.AddRecords(p.ProductId, product); if (m_manualUpSell.Enabled) m_manualUpSell.AddRecords(p.ProductId, product); }
protected override string GetCatalog() { var stopWatch = new StopWatch(true); var products = new List<ProductRecord>(); //get product count var countXml = CallCartApi("products/count", "products"); var countVal = countXml.Elements("count").First().Value; int pRows = Convert.ToInt16(countVal); //setup progress display var result = string.Format("{0}{1}: ({2} items) ", Environment.NewLine, CatalogFilename, countVal); ProgressText += result + "Extracting..."; string tempDisplay = ProgressText; //first get all the images because there can be many images for each product so record pages are not aligned countXml = CallCartApi("products/images/count", "images"); countVal = countXml.Elements("count").First().Value; int iRows = Convert.ToInt16(countVal); int pages = (int)Math.Ceiling( (decimal)iRows / (decimal)250 ); //can only get 250 products at a time var imagesXml = new List<XElement>(); //this will hold all images for entire catalog for (int page = 1; page <= pages; page++) { string paging = string.Format("?page={0}&limit=250", page); var pageXml = CallCartApi("products/images" + paging, "images"); if (pageXml == null) break; imagesXml.AddRange(pageXml.Elements("image")); ProgressText = string.Format("{1}{0}{2} Images ({3})", Environment.NewLine, tempDisplay, imagesXml.Count, stopWatch.Lap()); } tempDisplay = ProgressText; #if DEBUG if (imagesXml.Count() != iRows) { var errMsg = string.Format("Error reading BigCommerce images\nReported count = {0}, actual count = {1}", iRows, imagesXml.Count()); m_log.WriteEntry(errMsg, EventLogEntryType.Information, m_alias); } #endif //Next get all the custom fields so we don't have to make a separate call for each product countXml = CallCartApi("products/customfields/count", "customfields"); countVal = countXml.Elements("count").First().Value; iRows = Convert.ToInt16(countVal); pages = (int)Math.Ceiling((decimal)iRows / (decimal)250); //can only get 250 products at a time var customFieldXml = new List<XElement>(); //this will hold all images for entire catalog for (int page = 1; page <= pages; page++) { string paging = string.Format("?page={0}&limit=250", page); var pageXml = CallCartApi("products/customfields" + paging, "customfields"); if (pageXml == null) break; customFieldXml.AddRange(pageXml.Elements("customfield")); ProgressText = string.Format("{1}{0}{2} Custom Fields ({3})", Environment.NewLine, tempDisplay, customFieldXml.Count, stopWatch.Lap()); } tempDisplay = ProgressText; //Next get all the Categories so we can construct the tree countXml = CallCartApi("categories/count", "categories"); countVal = countXml.Elements("count").First().Value; iRows = Convert.ToInt16(countVal); pages = (int)Math.Ceiling((decimal)iRows / (decimal)250); //can only get 250 products at a time var categoryXml = new List<XElement>(); //this will hold all images for entire catalog for (int page = 1; page <= pages; page++) { string paging = string.Format("?page={0}&limit=250", page); var pageXml = CallCartApi("categories" + paging, "categories"); if (pageXml == null) break; categoryXml.AddRange(pageXml.Elements("category")); ProgressText = string.Format("{1}{0}{2} Categories ({3})", Environment.NewLine, tempDisplay, categoryXml.Count, stopWatch.Lap()); } SetCategoryParents(categoryXml); ProgressText += Environment.NewLine; tempDisplay = ProgressText; //now get each page of products pages = (int)Math.Ceiling((decimal)pRows / (decimal)250); //can only get 250 products at a time IEnumerable<XElement> productsXml = null; //this will only hold a single page of products int errors = 0; pRows = 0; for (int page = 1; page <= pages; page++) { string paging = string.Format("?page={0}&limit=250", page); productsXml = CallCartApi("products" + paging, "products"); if (productsXml == null) { errors++; //not necessarily an error break; } var productElements = productsXml.Elements("product"); foreach (var product in productElements) { try { var p = new ProductRecord { Name = Client.GetValue(product, "name"), ProductId = Client.GetValue(product, "id"), Att2Id = Client.GetValue(product, "brand_id"), Price = Client.GetValue(product, "price"), SalePrice = Client.GetValue(product, "sale_price"), Filter = string.Empty, Rating = Client.GetValue(product, "rating_total"), StandardCode = Client.GetValue(product, "upc"), Link = Client.GetValue(product, "custom_url"), ImageLink = string.Empty }; p.ImageLink = GetProductImage(imagesXml, p.ProductId); p.Att1Id = GetProductCategories(product.Element("categories")); if (p.StandardCode == null) p.StandardCode = string.Empty; #if DEBUG if (p.ProductId.Equals("11348") || p.ProductId.Equals("11012")) { var test = CallCartApi(string.Format("products/{0}/customfields", p.ProductId), "customfields"); var s = "break here"; } #endif var customFields = GetProductCustomFields(customFieldXml, p.ProductId); if (customFields.Any()) product.Add(customFields); //check category conditions, exclusions, and filters ApplyRules(ref p, product); products.Add(p); } catch { errors++; } ProgressText = string.Format("{0}{1} items completed, {2} errors ({3})", tempDisplay, ++pRows, errors, stopWatch.Lap()); } } if (products.Count < 1) return result + "(no data)"; var pCount = string.Format("({0} items) ", products.Count); ProgressText = string.Format("{0}{1} items completed ({2}){3}Uploading to server...", tempDisplay, pCount, stopWatch.Lap(), Environment.NewLine); result += m_boostService.WriteTable(m_alias, CatalogFilename, products); stopWatch.Stop(); return result; }
/// <summary> /// Bind catalog data to CatalogItem(s) /// </summary> /// <param name="Content"></param> internal List<ProductRecord> SetCatalogData(Stream Content) { List<ProductRecord> products = new List<ProductRecord>(); StreamReader rdr = new StreamReader(Content); string sContent = rdr.ReadToEnd(); /* * * ? sContent "[[\"ProductID (Yes) \", \"Name (Yes) \", \"CategoryIDs (Yes) \", \"BrandID (No) \", \"Price (Yes) \", \"SalePrice (No) \", \"Link (Yes) \", \"ImageLink (Yes) \", \"StandardCode (No)\", \"ActiveFlag (Yes)\", \"StockLevel (No)\"], * [\"product1\", \"product1\", \"\", \"\", \"5.00\", \"\", \"http:\\/\\/4-tell.coolcommerce.net\\/mm5\\/merchant.mvc\\u003fStore_code\\u003d4tell\\u0026amp\\u003bScreen\\u003dPROD\\u0026amp\\u003bProduct_Code\\u003dproduct1\", \"\", \"product1\", \"0\", \"\"], [\"product2\", \"product2\", \"test4,test5\", \"\", \"110.00\", \"\", \"http:\\/\\/4-tell.coolcommerce.net\\/mm5\\/merchant.mvc\\u003fStore_code\\u003d4tell\\u0026amp\\u003bScreen\\u003dPROD\\u0026amp\\u003bProduct_Code\\u003dproduct2\", \"\", \"product2\", \"1\", \"\"], [\"product3\", \"product3\", \"\", \"\", \"1.22\", \"\", \"http:\\/\\/4-tell.coolcommerce.net\\/mm5\\/merchant.mvc\\u003fStore_code\\u003d4tell\\u0026amp\\u003bScreen\\u003dPROD\\u0026amp\\u003bProduct_Code\\u003dproduct3\", \"\", \"product3\", \"1\", \"\"], [\"product4\", \"product4\", \"test1\", \"\", \"55.19\", \"\", \"http:\\/\ \/4-tell.coolcommerce.net\\/mm5\\/merchant.mvc\\u003fStore_code\\u003d4tell\\u0026amp\\u003bScreen\\u003dPROD\\u0026amp\\u003bProduct_Code\\u003dproduct4\", \"\", \"product4\", \"1\", \"\"]] * */ string[] rows = sContent.Trim().Split(']'); string thisRow = String.Empty; foreach (string row in rows) { if (row.Length > 0) { thisRow = row; thisRow = thisRow.Replace("[", String.Empty); thisRow = thisRow.Replace("]", String.Empty); ProductRecord pr = new ProductRecord(); if (! row.StartsWith("[[") == true && ! row.EndsWith("]]") == true) { // normal row string[] cols = thisRow.Split(','); // \"ProductID\", pr.ProductId = cols[1].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"Name\", pr.Name = cols[2].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"CategoryIDs\", pr.CategoryIDs = cols[3].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"BrandID\", pr.BrandID = cols[4].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"Price\", pr.Price = cols[5].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"SalePrice\", pr.SalePrice = cols[6].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"Link\", pr.Link = cols[7].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"ImageLink\", pr.ImageLink = cols[8].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"StandardCode \", pr.StandardCode = cols[9].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"ActiveFlag\", pr.ActiveFlag = cols[10].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); // \"StockLevel\"], pr.StockLevel = cols[11].Replace("\\", String.Empty).Replace("/", String.Empty).Replace('"', ' ').Trim(); products.Add(pr); } } } return products; }