Esempio n. 1
0
 private bool HasRequiredFields(ProductCsvImportLine csvLine, CsvProductInfo csvProduct)
 {
     if (string.IsNullOrEmpty(csvProduct.ImportAction))
     {
         csvLine.Status    = ProductImportStatus.Error;
         csvLine.StatusMsg = "ImportAction is required";
         return(false);
     }
     else if (importAction == ImportActionType.UNKNOWN)
     {
         csvLine.Status    = ProductImportStatus.Error;
         csvLine.StatusMsg = "Unknown ImportAction. Valid values are: 'C', 'R', 'U', 'D'";
         return(false);
     }
     if (string.IsNullOrEmpty(csvProduct.Name))
     {
         csvLine.Status    = ProductImportStatus.Error;
         csvLine.StatusMsg = "Name is required";
         return(false);
     }
     if (string.IsNullOrEmpty(csvProduct.UrlName))
     {
         csvLine.Status    = ProductImportStatus.Error;
         csvLine.StatusMsg = "UrlName is required";
         return(false);
     }
     return(true);
 }
Esempio n. 2
0
        private void CreateProduct(CsvProductInfo csvProduct)
        {
            var p = new Product();

            p.StoreId = storeId;

            ReplaceProduct(p, csvProduct);
        }
Esempio n. 3
0
        /// <summary>
        /// Get the file paths for Product Photos to be imported.
        /// Will grab photos from the CSV field and also photos with matching SKUs (StartsWith) from the ImportFiles directory.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="csvProduct"></param>
        /// <returns></returns>
        private IEnumerable <string> GetPhotoFilePathsForImport(Product p, CsvProductInfo csvProduct)
        {
            List <string> filenames = new List <string>();

            // CSV field
            filenames.AddRange(csvProduct.PhotoFilenames.ToList(",", true));

            // ImportFiles Directory - match by SKU
            if (!string.IsNullOrEmpty(p.Sku))
            {
                filenames.AddRange(filesInImportDirectory.FindAll(f =>
                                                                  f.StartsWith(p.Sku) &&
                                                                  (f.EndsWith(".jpg") || f.EndsWith(".gif") || f.EndsWith(".png"))
                                                                  ));
            }

            return(filenames.ConvertAll(f => Path.Combine(importFilesFolderFileRoot, f)));
        }
Esempio n. 4
0
        /// <summary>
        /// Updates an existing product.
        /// A field is only updated if the CSV field is non-empty.
        /// Existing Product Categories are kept, and new Categories are added from the CSV file.
        /// Existing Product Photos are kept, and new Photos are added.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="csvProduct"></param>
        private void UpdateProduct(Product p, CsvProductInfo csvProduct)
        {
            if (NotEmpty(csvProduct.Name))
            {
                p.Name = csvProduct.Name;
            }
            if (NotEmpty(csvProduct.Sku))
            {
                p.Sku = csvProduct.Sku;
            }
            if (NotEmpty(csvProduct.UrlName))
            {
                p.Slug = csvProduct.UrlName.IsValidSlug() ? csvProduct.UrlName : csvProduct.UrlName.CreateSlug();
            }
            if (csvProduct.Price.HasValue)
            {
                p.Price = csvProduct.Price;
            }
            if (csvProduct.Weight.HasValue)
            {
                p.Weight = csvProduct.Weight;
            }
            if (NotEmpty(csvProduct.SeoTitle))
            {
                p.SeoTitle = csvProduct.SeoTitle;
            }
            if (NotEmpty(csvProduct.SeoDescription))
            {
                p.SeoDescription = csvProduct.SeoDescription;
            }
            if (NotEmpty(csvProduct.SeoKeywords))
            {
                p.SeoKeywords = csvProduct.SeoKeywords;
            }
            if (csvProduct.IsActive.HasValue)
            {
                p.IsActive = csvProduct.IsActive;
            }
            if (csvProduct.TaxableItem.HasValue)
            {
                p.IsTaxable = csvProduct.TaxableItem;
            }
            if (csvProduct.ShowPrice.HasValue)
            {
                p.IsPriceDisplayed = csvProduct.ShowPrice;
            }
            if (csvProduct.AvailableForPurchase.HasValue)
            {
                p.IsAvailableForPurchase = csvProduct.AvailableForPurchase;
            }
            if (csvProduct.EnableInventoryManagement.HasValue)
            {
                p.InventoryIsEnabled = csvProduct.EnableInventoryManagement;
            }
            p.InventoryQtyInStock = csvProduct.StockLevel.HasValue ? csvProduct.StockLevel : null;

            if (csvProduct.AllowNegativeStock.HasValue)
            {
                p.InventoryAllowNegativeStockLevel = csvProduct.AllowNegativeStock;
            }

            if (!p.Slug.IsValidSlug())
            {
                csvLine.Status     = ProductImportStatus.Error;
                csvLine.StatusMsg += string.Format(@"Invalid Slug '{0}' must match the pattern '{1}'", p.Slug, RegexPatterns.IsValidSlug);
                return;
            }
            if (!string.IsNullOrEmpty(p.Sku) && !p.Sku.IsValidSku())
            {
                csvLine.Status     = ProductImportStatus.Error;
                csvLine.StatusMsg += string.Format(@"Invalid Sku '{0}' must match the pattern '{1}'", p.Sku, RegexPatterns.IsValidSku);
                return;
            }

            //--- Digital File
            if (NotEmpty(csvProduct.DigitalFilename))
            {
                if (NotEmpty(p.DigitalFilename))
                {
                    File.Delete(Path.Combine(productFilesFolderFileRoot, p.DigitalFilename));
                }
                ImportDigitalFile(p, csvProduct.DigitalFilename);
            }

            //--- Descriptors (update/add if different, but preserve existing)
            using (esTransactionScope transaction = new esTransactionScope())
            {
                var existingDescriptors = p.GetProductDescriptors();
                var newDescriptors      = new Dictionary <int, DescriptorInfo>();
                for (short i = 0; i < 5; i++)
                {
                    //var descriptor = (i < existingDescriptors.Count) ? existingDescriptors[i] : new ProductDescriptor();
                    //descriptor.SortOrder = i;
                    //newDescriptors[i] = descriptor;

                    if (i < existingDescriptors.Count)
                    {
                        newDescriptors[i] = new DescriptorInfo()
                        {
                            Name = existingDescriptors[i].Name, Text = existingDescriptors[i].Text
                        };
                    }
                    else
                    {
                        newDescriptors[i] = new DescriptorInfo();
                    }
                }
                if (NotEmpty(csvProduct.Desc1Name))
                {
                    newDescriptors[0].Name = csvProduct.Desc1Name;
                }
                if (NotEmpty(csvProduct.Desc2Name))
                {
                    newDescriptors[1].Name = csvProduct.Desc2Name;
                }
                if (NotEmpty(csvProduct.Desc3Name))
                {
                    newDescriptors[2].Name = csvProduct.Desc3Name;
                }
                if (NotEmpty(csvProduct.Desc4Name))
                {
                    newDescriptors[3].Name = csvProduct.Desc4Name;
                }
                if (NotEmpty(csvProduct.Desc5Name))
                {
                    newDescriptors[4].Name = csvProduct.Desc5Name;
                }
                if (NotEmpty(csvProduct.Desc1Html))
                {
                    newDescriptors[0].Text = csvProduct.Desc1Html;
                }
                if (NotEmpty(csvProduct.Desc2Html))
                {
                    newDescriptors[1].Text = csvProduct.Desc2Html;
                }
                if (NotEmpty(csvProduct.Desc3Html))
                {
                    newDescriptors[2].Text = csvProduct.Desc3Html;
                }
                if (NotEmpty(csvProduct.Desc4Html))
                {
                    newDescriptors[3].Text = csvProduct.Desc4Html;
                }
                if (NotEmpty(csvProduct.Desc5Html))
                {
                    newDescriptors[4].Text = csvProduct.Desc5Html;
                }

                p.ProductDescriptorCollectionByProductId.MarkAllAsDeleted();
                for (short i = 0; i < newDescriptors.Count; i++)
                {
                    var descr = newDescriptors[i];
                    if (NotEmpty(descr.Name) || NotEmpty(descr.Text))
                    {
                        AddProductDescriptor(p, i, descr.Name, descr.Text);
                    }
                }

                transaction.Complete();
            }

            //--- Categories (add new, but don't delete existing)
            List <Category> existingProductCategories = p.GetCategories(true);
            List <string>   newCategoryNames          = csvProduct.CategoryNames.ToList(",", true);

            newCategoryNames.RemoveAll(x => existingProductCategories.Exists(c => c.Name == x));
            foreach (string newCat in newCategoryNames)
            {
                var c = Category.GetByName(storeId, newCat) ?? CreateCategory(newCat);
                p.AddCategory(c);
            }

            //--- Photos (add new, but don't delete existing)
            IEnumerable <string> importPhotoFiles = GetPhotoFilePathsForImport(p, csvProduct);

            foreach (string filepath in importPhotoFiles)
            {
                AddPhoto(p, filepath);
            }

            p.Save();
        }
Esempio n. 5
0
        /// <summary>
        /// Replaces/overwrites fields on an existing Product.
        /// ALL matching fields are replaced/overwritten with the values from the CSV file (including empty fields).
        /// Existing Product Categories are first DELETED, and then re-added from the CSV file.
        /// Existing Product Photos are DELETED, and then re-added from the CSV.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="csvProduct"></param>
        private void ReplaceProduct(Product p, CsvProductInfo csvProduct)
        {
            p.Name                             = csvProduct.Name;
            p.Sku                              = csvProduct.Sku;
            p.Slug                             = csvProduct.UrlName.IsValidSlug() ? csvProduct.UrlName : csvProduct.UrlName.CreateSlug();
            p.Price                            = csvProduct.Price;
            p.Weight                           = csvProduct.Weight;
            p.SeoTitle                         = csvProduct.SeoTitle;
            p.SeoDescription                   = csvProduct.SeoDescription;
            p.SeoKeywords                      = csvProduct.SeoKeywords;
            p.IsActive                         = csvProduct.IsActive.GetValueOrDefault(true);
            p.IsTaxable                        = csvProduct.TaxableItem.GetValueOrDefault(true);
            p.IsPriceDisplayed                 = csvProduct.ShowPrice.GetValueOrDefault(true);
            p.IsAvailableForPurchase           = csvProduct.AvailableForPurchase.GetValueOrDefault(true);
            p.InventoryIsEnabled               = csvProduct.EnableInventoryManagement.GetValueOrDefault(false);
            p.InventoryQtyInStock              = csvProduct.StockLevel;
            p.InventoryAllowNegativeStockLevel = csvProduct.AllowNegativeStock.GetValueOrDefault(false);

            if (!p.Slug.IsValidSlug())
            {
                csvLine.Status     = ProductImportStatus.Error;
                csvLine.StatusMsg += string.Format(@"Invalid Slug '{0}' must match the pattern '{1}'", p.Slug, RegexPatterns.IsValidSlug);
                return;
            }
            if (!string.IsNullOrEmpty(p.Sku) && !p.Sku.IsValidSku())
            {
                csvLine.Status     = ProductImportStatus.Error;
                csvLine.StatusMsg += string.Format(@"Invalid Sku '{0}' must match the pattern '{1}'", p.Sku, RegexPatterns.IsValidSku);
                return;
            }

            // save now so we can get an ID for new products
            p.Save();

            //--- Digital File
            if (NotEmpty(p.DigitalFilename))
            {
                File.Delete(Path.Combine(productFilesFolderFileRoot, p.DigitalFilename));
                p.DigitalFilename        = "";
                p.DigitalFileDisplayName = "";
                p.DeliveryMethodId       = (short)ProductDeliveryMethod.Shipped;
            }
            ImportDigitalFile(p, csvProduct.DigitalFilename);

            //--- Descriptors (delete and re-add)
            using (esTransactionScope transaction = new esTransactionScope())
            {
                p.ProductDescriptorCollectionByProductId.MarkAllAsDeleted();
                AddProductDescriptor(p, 1, csvProduct.Desc1Name, csvProduct.Desc1Html); // always add the 1st tab
                if (!string.IsNullOrEmpty(csvProduct.Desc2Name))
                {
                    AddProductDescriptor(p, 2, csvProduct.Desc2Name, csvProduct.Desc2Html);
                }
                if (!string.IsNullOrEmpty(csvProduct.Desc3Name))
                {
                    AddProductDescriptor(p, 3, csvProduct.Desc3Name, csvProduct.Desc3Html);
                }
                if (!string.IsNullOrEmpty(csvProduct.Desc4Name))
                {
                    AddProductDescriptor(p, 4, csvProduct.Desc4Name, csvProduct.Desc4Html);
                }
                if (!string.IsNullOrEmpty(csvProduct.Desc5Name))
                {
                    AddProductDescriptor(p, 5, csvProduct.Desc5Name, csvProduct.Desc5Html);
                }

                transaction.Complete();
            }

            //--- Categories (delete and then re-associate/add)
            p.ProductCategoryCollectionByProductId.MarkAllAsDeleted(); // remove existing product categories
            //p.ProductCategoryCollectionByProductId.Save();
            List <string> newCategoryNames = csvProduct.CategoryNames.ToList(",", true);

            foreach (string newCat in newCategoryNames)
            {
                var c = Category.GetByName(storeId, newCat) ?? CreateCategory(newCat);
                p.AddCategory(c);
            }

            //--- Photos (delete and then re-add)
            p.DeleteAllPhotos(productPhotoFolderFileRoot);
            IEnumerable <string> importPhotoFiles = GetPhotoFilePathsForImport(p, csvProduct);

            foreach (string filepath in importPhotoFiles)
            {
                AddPhoto(p, filepath);
            }

            p.Save();
        }
Esempio n. 6
0
        protected void btnDownloadCsv_Click(object sender, EventArgs e)
        {
            var productList = DataModel.ProductCollection.GetAll(StoreContext.CurrentStore.Id.Value);

            productList.Sort((left, right) => left.Id.Value.CompareTo(right.Id.Value));

            List <CsvProductInfo> csvProducts = new List <CsvProductInfo>();

            foreach (Product p in productList)
            {
                var csv = new CsvProductInfo()
                {
                    ImportAction              = "",
                    ProductId                 = p.Id.Value,
                    Name                      = p.Name,
                    Sku                       = p.Sku,
                    UrlName                   = p.Slug,
                    Price                     = p.Price,
                    Weight                    = p.Weight,
                    SeoTitle                  = p.SeoTitle,
                    SeoDescription            = p.SeoDescription,
                    SeoKeywords               = p.SeoKeywords,
                    IsActive                  = p.IsActive,
                    CategoryNames             = p.GetCategories(true).ConvertAll(c => c.Name).ToDelimitedString(", "),
                    PhotoFilenames            = p.GetAllPhotosInSortOrder().ConvertAll(x => x.Filename).ToDelimitedString(", "),
                    DigitalFilename           = p.DigitalFilename,
                    TaxableItem               = p.IsTaxable,
                    ShowPrice                 = p.IsPriceDisplayed,
                    AvailableForPurchase      = p.IsAvailableForPurchase,
                    EnableInventoryManagement = p.InventoryIsEnabled,
                    StockLevel                = p.InventoryQtyInStock,
                    AllowNegativeStock        = p.InventoryAllowNegativeStockLevel
                };
                var descriptors = p.GetProductDescriptors();
                if (descriptors.Count >= 1)
                {
                    csv.Desc1Name = descriptors[0].Name;
                    csv.Desc1Html = descriptors[0].TextHtmlDecoded;
                }
                if (descriptors.Count >= 2)
                {
                    csv.Desc2Name = descriptors[1].Name;
                    csv.Desc2Html = descriptors[1].TextHtmlDecoded;
                }
                if (descriptors.Count >= 3)
                {
                    csv.Desc3Name = descriptors[2].Name;
                    csv.Desc3Html = descriptors[2].TextHtmlDecoded;
                }
                if (descriptors.Count >= 4)
                {
                    csv.Desc4Name = descriptors[3].Name;
                    csv.Desc4Html = descriptors[3].TextHtmlDecoded;
                }
                if (descriptors.Count >= 5)
                {
                    csv.Desc5Name = descriptors[4].Name;
                    csv.Desc5Html = descriptors[4].TextHtmlDecoded;
                }

                csvProducts.Add(csv);
            }

            Response.Clear();
            Response.ClearHeaders();
            Response.ContentType = "text/csv";
            Response.AddHeader("Content-Disposition", "attachment; filename=Product-Export.csv");

            var exporter = new ProductCsvImporter(StoreContext.CurrentStore.Id.Value);

            exporter.ExportProducts(csvProducts, Response.OutputStream);

            Response.Flush();
            Response.End();
        }