public void Can_save_and_load_productVariantAttributeValue() { var pvav = new ProductVariantAttributeValue { Name = "Name 1", ColorSquaresRgb = "12FF33", PriceAdjustment = 1.1M, WeightAdjustment = 2.1M, IsPreSelected = true, DisplayOrder = 3, ProductVariantAttribute = new ProductVariantAttribute { TextPrompt = "TextPrompt 1", IsRequired = true, AttributeControlType = AttributeControlType.DropdownList, DisplayOrder = 1, ProductVariant = new ProductVariant() { Name = "Product variant name 1", CreatedOnUtc = new DateTime(2010, 01, 03), UpdatedOnUtc = new DateTime(2010, 01, 04), Product = new Product() { Name = "Name 1", Published = true, Deleted = false, CreatedOnUtc = new DateTime(2010, 01, 01), UpdatedOnUtc = new DateTime(2010, 01, 02), } }, ProductAttribute = new ProductAttribute() { Name = "Name 1", Description = "Description 1", } } }; var fromDb = SaveAndLoadEntity(pvav); fromDb.ShouldNotBeNull(); fromDb.Name.ShouldEqual("Name 1"); fromDb.ColorSquaresRgb.ShouldEqual("12FF33"); fromDb.PriceAdjustment.ShouldEqual(1.1M); fromDb.WeightAdjustment.ShouldEqual(2.1M); fromDb.IsPreSelected.ShouldEqual(true); fromDb.DisplayOrder.ShouldEqual(3); fromDb.ProductVariantAttribute.ShouldNotBeNull(); fromDb.ProductVariantAttribute.TextPrompt.ShouldEqual("TextPrompt 1"); }
public void Can_save_and_load_productVariantAttributeValue() { var pvav = new ProductVariantAttributeValue { AttributeValueType = AttributeValueType.AssociatedToProduct, AssociatedProductId = 10, Name = "Name 1", ColorSquaresRgb = "12FF33", PriceAdjustment = 1.1M, WeightAdjustment = 2.1M, Cost = 3.1M, Quantity = 2, IsPreSelected = true, DisplayOrder = 3, ProductVariantAttribute = new ProductVariantAttribute { TextPrompt = "TextPrompt 1", IsRequired = true, AttributeControlType = AttributeControlType.DropdownList, DisplayOrder = 1, Product = GetTestProduct(), ProductAttribute = new ProductAttribute() { Name = "Name 1", Description = "Description 1", } } }; var fromDb = SaveAndLoadEntity(pvav); fromDb.ShouldNotBeNull(); fromDb.AttributeValueType.ShouldEqual(AttributeValueType.AssociatedToProduct); fromDb.AssociatedProductId.ShouldEqual(10); fromDb.Name.ShouldEqual("Name 1"); fromDb.ColorSquaresRgb.ShouldEqual("12FF33"); fromDb.PriceAdjustment.ShouldEqual(1.1M); fromDb.WeightAdjustment.ShouldEqual(2.1M); fromDb.Cost.ShouldEqual(3.1M); fromDb.Quantity.ShouldEqual(2); fromDb.IsPreSelected.ShouldEqual(true); fromDb.DisplayOrder.ShouldEqual(3); fromDb.ProductVariantAttribute.ShouldNotBeNull(); fromDb.ProductVariantAttribute.TextPrompt.ShouldEqual("TextPrompt 1"); }
/// <summary> /// Updates the product variant attribute value /// </summary> /// <param name="productVariantAttributeValue">The product variant attribute value</param> public virtual void UpdateProductVariantAttributeValue(ProductVariantAttributeValue productVariantAttributeValue) { if (productVariantAttributeValue == null) throw new ArgumentNullException("productVariantAttributeValue"); _productVariantAttributeValueRepository.Update(productVariantAttributeValue); _cacheManager.RemoveByPattern(PRODUCTATTRIBUTES_PATTERN_KEY); _cacheManager.RemoveByPattern(PRODUCTVARIANTATTRIBUTES_PATTERN_KEY); _cacheManager.RemoveByPattern(PRODUCTVARIANTATTRIBUTEVALUES_PATTERN_KEY); //event notification _eventPublisher.EntityUpdated(productVariantAttributeValue); }
/// <summary> /// Create a copy of product variant with all depended data /// </summary> /// <param name="productVariant">The product variant to copy</param> /// <param name="productId">The product identifier</param> /// <param name="newName">The name of product variant duplicate</param> /// <param name="isPublished">A value indicating whether the product variant duplicate should be published</param> /// <param name="copyImage">A value indicating whether the product variant image should be copied</param> /// <returns>Product variant copy</returns> public virtual ProductVariant CopyProductVariant(ProductVariant productVariant, int productId, string newName, bool isPublished, bool copyImage) { if (productVariant == null) throw new ArgumentNullException("productVariant"); var languages = _languageService.GetAllLanguages(true); // product variant picture int pictureId = 0; if (copyImage) { var picture = _pictureService.GetPictureById(productVariant.PictureId); if (picture != null) { var pictureCopy = _pictureService.InsertPicture( _pictureService.LoadPictureBinary(picture), picture.MimeType, _pictureService.GetPictureSeName(productVariant.Name), true); pictureId = pictureCopy.Id; } } // product variant download & sample download int downloadId = productVariant.DownloadId; int sampleDownloadId = productVariant.SampleDownloadId; if (productVariant.IsDownload) { var download = _downloadService.GetDownloadById(productVariant.DownloadId); if (download != null) { var downloadCopy = new Download() { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = download.UseDownloadUrl, DownloadUrl = download.DownloadUrl, DownloadBinary = download.DownloadBinary, ContentType = download.ContentType, Filename = download.Filename, Extension = download.Extension, IsNew = download.IsNew, }; _downloadService.InsertDownload(downloadCopy); downloadId = downloadCopy.Id; } if (productVariant.HasSampleDownload) { var sampleDownload = _downloadService.GetDownloadById(productVariant.SampleDownloadId); if (sampleDownload != null) { var sampleDownloadCopy = new Download() { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = sampleDownload.UseDownloadUrl, DownloadUrl = sampleDownload.DownloadUrl, DownloadBinary = sampleDownload.DownloadBinary, ContentType = sampleDownload.ContentType, Filename = sampleDownload.Filename, Extension = sampleDownload.Extension, IsNew = sampleDownload.IsNew }; _downloadService.InsertDownload(sampleDownloadCopy); sampleDownloadId = sampleDownloadCopy.Id; } } } // product variant var productVariantCopy = new ProductVariant() { ProductId = productId, Name = newName, Sku = productVariant.Sku, Description = productVariant.Description, AdminComment = productVariant.AdminComment, ManufacturerPartNumber = productVariant.ManufacturerPartNumber, Gtin = productVariant.Gtin, IsGiftCard = productVariant.IsGiftCard, GiftCardType = productVariant.GiftCardType, RequireOtherProducts = productVariant.RequireOtherProducts, RequiredProductVariantIds = productVariant.RequiredProductVariantIds, AutomaticallyAddRequiredProductVariants = productVariant.AutomaticallyAddRequiredProductVariants, IsDownload = productVariant.IsDownload, DownloadId = downloadId, UnlimitedDownloads = productVariant.UnlimitedDownloads, MaxNumberOfDownloads = productVariant.MaxNumberOfDownloads, DownloadExpirationDays = productVariant.DownloadExpirationDays, DownloadActivationType = productVariant.DownloadActivationType, HasSampleDownload = productVariant.HasSampleDownload, SampleDownloadId = sampleDownloadId, HasUserAgreement = productVariant.HasUserAgreement, UserAgreementText = productVariant.UserAgreementText, IsRecurring = productVariant.IsRecurring, RecurringCycleLength = productVariant.RecurringCycleLength, RecurringCyclePeriod = productVariant.RecurringCyclePeriod, RecurringTotalCycles = productVariant.RecurringTotalCycles, IsShipEnabled = productVariant.IsShipEnabled, IsFreeShipping = productVariant.IsFreeShipping, AdditionalShippingCharge = productVariant.AdditionalShippingCharge, IsTaxExempt = productVariant.IsTaxExempt, TaxCategoryId = productVariant.TaxCategoryId, ManageInventoryMethod = productVariant.ManageInventoryMethod, StockQuantity = productVariant.StockQuantity, DisplayStockAvailability = productVariant.DisplayStockAvailability, DisplayStockQuantity = productVariant.DisplayStockQuantity, MinStockQuantity = productVariant.MinStockQuantity, LowStockActivityId = productVariant.LowStockActivityId, NotifyAdminForQuantityBelow = productVariant.NotifyAdminForQuantityBelow, BackorderMode = productVariant.BackorderMode, AllowBackInStockSubscriptions = productVariant.AllowBackInStockSubscriptions, OrderMinimumQuantity = productVariant.OrderMinimumQuantity, OrderMaximumQuantity = productVariant.OrderMaximumQuantity, AllowedQuantities = productVariant.AllowedQuantities, DisableBuyButton = productVariant.DisableBuyButton, DisableWishlistButton = productVariant.DisableWishlistButton, CallForPrice = productVariant.CallForPrice, Price = productVariant.Price, OldPrice = productVariant.OldPrice, ProductCost = productVariant.ProductCost, SpecialPrice = productVariant.SpecialPrice, SpecialPriceStartDateTimeUtc = productVariant.SpecialPriceStartDateTimeUtc, SpecialPriceEndDateTimeUtc = productVariant.SpecialPriceEndDateTimeUtc, CustomerEntersPrice = productVariant.CustomerEntersPrice, MinimumCustomerEnteredPrice = productVariant.MinimumCustomerEnteredPrice, MaximumCustomerEnteredPrice = productVariant.MaximumCustomerEnteredPrice, Weight = productVariant.Weight, Length = productVariant.Length, Width = productVariant.Width, Height = productVariant.Height, PictureId = pictureId, AvailableStartDateTimeUtc = productVariant.AvailableStartDateTimeUtc, AvailableEndDateTimeUtc = productVariant.AvailableEndDateTimeUtc, Published = isPublished, Deleted = productVariant.Deleted, DisplayOrder = productVariant.DisplayOrder, CreatedOnUtc = DateTime.UtcNow, UpdatedOnUtc = DateTime.UtcNow }; _productService.InsertProductVariant(productVariantCopy); //localization foreach (var lang in languages) { var name = productVariant.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(productVariantCopy, x => x.Name, name, lang.Id); var description = productVariant.GetLocalized(x => x.Description, lang.Id, false, false); if (!String.IsNullOrEmpty(description)) _localizedEntityService.SaveLocalizedValue(productVariantCopy, x => x.Description, description, lang.Id); } // product variant <-> attributes mappings var associatedAttributes = new Dictionary<int, int>(); var associatedAttributeValues = new Dictionary<int, int>(); foreach (var productVariantAttribute in _productAttributeService.GetProductVariantAttributesByProductVariantId(productVariant.Id)) { var productVariantAttributeCopy = new ProductVariantAttribute() { ProductVariantId = productVariantCopy.Id, ProductAttributeId = productVariantAttribute.ProductAttributeId, TextPrompt = productVariantAttribute.TextPrompt, IsRequired = productVariantAttribute.IsRequired, AttributeControlTypeId = productVariantAttribute.AttributeControlTypeId, DisplayOrder = productVariantAttribute.DisplayOrder }; _productAttributeService.InsertProductVariantAttribute(productVariantAttributeCopy); //save associated value (used for combinations copying) associatedAttributes.Add(productVariantAttribute.Id, productVariantAttributeCopy.Id); // product variant attribute values var productVariantAttributeValues = _productAttributeService.GetProductVariantAttributeValues(productVariantAttribute.Id); foreach (var productVariantAttributeValue in productVariantAttributeValues) { var pvavCopy = new ProductVariantAttributeValue() { ProductVariantAttributeId = productVariantAttributeCopy.Id, Name = productVariantAttributeValue.Name, ColorSquaresRgb = productVariantAttributeValue.ColorSquaresRgb, PriceAdjustment = productVariantAttributeValue.PriceAdjustment, WeightAdjustment = productVariantAttributeValue.WeightAdjustment, IsPreSelected = productVariantAttributeValue.IsPreSelected, DisplayOrder = productVariantAttributeValue.DisplayOrder }; _productAttributeService.InsertProductVariantAttributeValue(pvavCopy); //save associated value (used for combinations copying) associatedAttributeValues.Add(productVariantAttributeValue.Id, pvavCopy.Id); //localization foreach (var lang in languages) { var name = productVariantAttributeValue.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(pvavCopy, x => x.Name, name, lang.Id); } } } foreach (var combination in _productAttributeService.GetAllProductVariantAttributeCombinations(productVariant.Id)) { //generate new AttributesXml according to new value IDs string newAttributesXml = ""; var parsedProductVariantAttributes = _productAttributeParser.ParseProductVariantAttributes(combination.AttributesXml); foreach (var oldPva in parsedProductVariantAttributes) { if (associatedAttributes.ContainsKey(oldPva.Id)) { int newPvaId = associatedAttributes[oldPva.Id]; var newPva = _productAttributeService.GetProductVariantAttributeById(newPvaId); if (newPva != null) { var oldPvaValuesStr = _productAttributeParser.ParseValues(combination.AttributesXml, oldPva.Id); foreach (var oldPvaValueStr in oldPvaValuesStr) { if (newPva.ShouldHaveValues()) { //attribute values int oldPvaValue = int.Parse(oldPvaValueStr); if (associatedAttributeValues.ContainsKey(oldPvaValue)) { int newPvavId = associatedAttributeValues[oldPvaValue]; var newPvav = _productAttributeService.GetProductVariantAttributeValueById(newPvavId); if (newPvav != null) { newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, newPvav.Id.ToString()); } } } else { //just a text newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, oldPvaValueStr); } } } } } var combinationCopy = new ProductVariantAttributeCombination() { ProductVariantId = productVariantCopy.Id, AttributesXml = newAttributesXml, StockQuantity = combination.StockQuantity, AllowOutOfStockOrders = combination.AllowOutOfStockOrders, Sku = combination.Sku, ManufacturerPartNumber = combination.ManufacturerPartNumber, Gtin = combination.Gtin }; _productAttributeService.InsertProductVariantAttributeCombination(combinationCopy); } // product variant tier prices foreach (var tierPrice in productVariant.TierPrices) { _productService.InsertTierPrice( new TierPrice() { ProductVariantId = productVariantCopy.Id, CustomerRoleId = tierPrice.CustomerRoleId, Quantity = tierPrice.Quantity, Price = tierPrice.Price }); } // product variant <-> discounts mapping foreach (var discount in productVariant.AppliedDiscounts) { productVariantCopy.AppliedDiscounts.Add(discount); _productService.UpdateProductVariant(productVariantCopy); } //update "HasTierPrices" and "HasDiscountsApplied" properties _productService.UpdateHasTierPricesProperty(productVariantCopy); _productService.UpdateHasDiscountsApplied(productVariantCopy); return productVariantCopy; }
/// <summary> /// Get a price adjustment of a product variant attribute value /// </summary> /// <param name="pvav">Product variant attribute value</param> /// <returns>price adjustment</returns> public virtual decimal GetProductVariantAttributeValuePriceAdjustment(ProductVariantAttributeValue pvav) { if (pvav == null) throw new ArgumentNullException("pvav"); var adjustment = decimal.Zero; switch (pvav.AttributeValueType) { case AttributeValueType.Simple: { //simple attribute adjustment = pvav.PriceAdjustment; } break; case AttributeValueType.AssociatedToProduct: { //bundled product var associatedProduct = _productService.GetProductById(pvav.AssociatedProductId); if (associatedProduct != null) { adjustment = GetFinalPrice(associatedProduct, true) * pvav.Quantity; } } break; default: break; } return adjustment; }
/// <summary> /// Creates a copy of product with all depended data /// </summary> /// <param name="productId">The product identifier</param> /// <param name="newName">The name of product duplicate</param> /// <param name="isPublished">A value indicating whether the product duplicate should be published</param> /// <param name="copyImages">A value indicating whether the product images should be copied</param> /// <returns>Product entity</returns> public Product CopyProduct(int productId, string newName, bool isPublished, bool copyImages) { var product = _productService.GetProductById(productId); if (product == null) throw new ArgumentException("No product found with the specified id", "productId"); Product productCopy = null; //uncomment this line to support transactions //using (var scope = new System.Transactions.TransactionScope()) { // product productCopy = new Product() { Name = newName, ShortDescription = product.ShortDescription, FullDescription = product.FullDescription, ProductTemplateId = product.ProductTemplateId, AdminComment = product.AdminComment, ShowOnHomePage = product.ShowOnHomePage, MetaKeywords = product.MetaKeywords, MetaDescription = product.MetaDescription, MetaTitle = product.MetaTitle, SeName = product.SeName, AllowCustomerReviews = product.AllowCustomerReviews, Published = isPublished, Deleted = product.Deleted, CreatedOnUtc = DateTime.UtcNow, UpdatedOnUtc = DateTime.UtcNow }; _productService.InsertProduct(productCopy); var languages = _languageService.GetAllLanguages(true); //localization foreach (var lang in languages) { var name = product.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.Name, name, lang.Id); var shortDescription = product.GetLocalized(x => x.ShortDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(shortDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.ShortDescription, shortDescription, lang.Id); var fullDescription = product.GetLocalized(x => x.FullDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(fullDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.FullDescription, fullDescription, lang.Id); var metaKeywords = product.GetLocalized(x => x.MetaKeywords, lang.Id, false, false); if (!String.IsNullOrEmpty(metaKeywords)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaKeywords, metaKeywords, lang.Id); var metaDescription = product.GetLocalized(x => x.MetaDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(metaDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaDescription, metaDescription, lang.Id); var metaTitle = product.GetLocalized(x => x.MetaTitle, lang.Id, false, false); if (!String.IsNullOrEmpty(metaTitle)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaTitle, metaTitle, lang.Id); var seName = product.GetLocalized(x => x.SeName, lang.Id, false, false); if (!String.IsNullOrEmpty(seName)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.SeName, seName, lang.Id); } //product tags foreach (var productTag in product.ProductTags) { productCopy.ProductTags.Add(productTag); } //ensure product is saved before updating totals _productService.UpdateProduct(product); foreach (var productTag in product.ProductTags) { _productTagService.UpdateProductTagTotals(productTag); } // product pictures if (copyImages) { foreach (var productPicture in product.ProductPictures) { var picture = productPicture.Picture; var pictureCopy = _pictureService.InsertPicture( _pictureService.LoadPictureBinary(picture), picture.MimeType, _pictureService.GetPictureSeName(newName), true); _productService.InsertProductPicture(new ProductPicture() { ProductId = productCopy.Id, PictureId = pictureCopy.Id, DisplayOrder = productPicture.DisplayOrder }); } } // product <-> categories mappings foreach (var productCategory in product.ProductCategories) { var productCategoryCopy = new ProductCategory() { ProductId = productCopy.Id, CategoryId = productCategory.CategoryId, IsFeaturedProduct = productCategory.IsFeaturedProduct, DisplayOrder = productCategory.DisplayOrder }; _categoryService.InsertProductCategory(productCategoryCopy); } // product <-> manufacturers mappings foreach (var productManufacturers in product.ProductManufacturers) { var productManufacturerCopy = new ProductManufacturer() { ProductId = productCopy.Id, ManufacturerId = productManufacturers.ManufacturerId, IsFeaturedProduct = productManufacturers.IsFeaturedProduct, DisplayOrder = productManufacturers.DisplayOrder }; _manufacturerService.InsertProductManufacturer(productManufacturerCopy); } // product <-> releated products mappings foreach (var relatedProduct in _productService.GetRelatedProductsByProductId1(product.Id, true)) { _productService.InsertRelatedProduct( new RelatedProduct() { ProductId1 = productCopy.Id, ProductId2 = relatedProduct.ProductId2, DisplayOrder = relatedProduct.DisplayOrder }); } // product <-> cross sells mappings foreach (var csProduct in _productService.GetCrossSellProductsByProductId1(product.Id, true)) { _productService.InsertCrossSellProduct( new CrossSellProduct() { ProductId1 = productCopy.Id, ProductId2 = csProduct.ProductId2, }); } // product specifications foreach (var productSpecificationAttribute in product.ProductSpecificationAttributes) { var psaCopy = new ProductSpecificationAttribute() { ProductId = productCopy.Id, SpecificationAttributeOptionId = productSpecificationAttribute.SpecificationAttributeOptionId, AllowFiltering = productSpecificationAttribute.AllowFiltering, ShowOnProductPage = productSpecificationAttribute.ShowOnProductPage, DisplayOrder = productSpecificationAttribute.DisplayOrder }; _specificationAttributeService.InsertProductSpecificationAttribute(psaCopy); } // product variants var productVariants = product.ProductVariants; foreach (var productVariant in productVariants) { // product variant picture int pictureId = 0; if (copyImages) { var picture = _pictureService.GetPictureById(productVariant.PictureId); if (picture != null) { var pictureCopy = _pictureService.InsertPicture( _pictureService.LoadPictureBinary(picture), picture.MimeType, _pictureService.GetPictureSeName(productVariant.Name), true); pictureId = pictureCopy.Id; } } // product variant download & sample download int downloadId = productVariant.DownloadId; int sampleDownloadId = productVariant.SampleDownloadId; if (productVariant.IsDownload) { var download = _downloadService.GetDownloadById(productVariant.DownloadId); if (download != null) { var downloadCopy = new Download() { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = download.UseDownloadUrl, DownloadUrl = download.DownloadUrl, DownloadBinary = download.DownloadBinary, ContentType = download.ContentType, Filename = download.Filename, Extension = download.Extension, IsNew = download.IsNew, }; _downloadService.InsertDownload(downloadCopy); downloadId = downloadCopy.Id; } if (productVariant.HasSampleDownload) { var sampleDownload = _downloadService.GetDownloadById(productVariant.SampleDownloadId); if (sampleDownload != null) { var sampleDownloadCopy = new Download() { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = sampleDownload.UseDownloadUrl, DownloadUrl = sampleDownload.DownloadUrl, DownloadBinary = sampleDownload.DownloadBinary, ContentType = sampleDownload.ContentType, Filename = sampleDownload.Filename, Extension = sampleDownload.Extension, IsNew = sampleDownload.IsNew }; _downloadService.InsertDownload(sampleDownloadCopy); sampleDownloadId = sampleDownloadCopy.Id; } } } // product variant var productVariantCopy = new ProductVariant() { ProductId = productCopy.Id, Name = productVariant.Name, Sku = productVariant.Sku, Description = productVariant.Description, AdminComment = productVariant.AdminComment, ManufacturerPartNumber = productVariant.ManufacturerPartNumber, Gtin = productVariant.Gtin, IsGiftCard = productVariant.IsGiftCard, GiftCardType = productVariant.GiftCardType, RequireOtherProducts = productVariant.RequireOtherProducts, RequiredProductVariantIds = productVariant.RequiredProductVariantIds, AutomaticallyAddRequiredProductVariants = productVariant.AutomaticallyAddRequiredProductVariants, IsDownload = productVariant.IsDownload, DownloadId = downloadId, UnlimitedDownloads = productVariant.UnlimitedDownloads, MaxNumberOfDownloads = productVariant.MaxNumberOfDownloads, DownloadExpirationDays = productVariant.DownloadExpirationDays, DownloadActivationType = productVariant.DownloadActivationType, HasSampleDownload = productVariant.HasSampleDownload, SampleDownloadId = sampleDownloadId, HasUserAgreement = productVariant.HasUserAgreement, UserAgreementText = productVariant.UserAgreementText, IsRecurring = productVariant.IsRecurring, RecurringCycleLength = productVariant.RecurringCycleLength, RecurringCyclePeriod = productVariant.RecurringCyclePeriod, RecurringTotalCycles = productVariant.RecurringTotalCycles, IsShipEnabled = productVariant.IsShipEnabled, IsFreeShipping = productVariant.IsFreeShipping, AdditionalShippingCharge = productVariant.AdditionalShippingCharge, IsTaxExempt = productVariant.IsTaxExempt, TaxCategoryId = productVariant.TaxCategoryId, ManageInventoryMethod = productVariant.ManageInventoryMethod, StockQuantity = productVariant.StockQuantity, DisplayStockAvailability = productVariant.DisplayStockAvailability, DisplayStockQuantity = productVariant.DisplayStockQuantity, MinStockQuantity = productVariant.MinStockQuantity, LowStockActivityId = productVariant.LowStockActivityId, NotifyAdminForQuantityBelow = productVariant.NotifyAdminForQuantityBelow, BackorderMode = productVariant.BackorderMode, AllowBackInStockSubscriptions = productVariant.AllowBackInStockSubscriptions, OrderMinimumQuantity = productVariant.OrderMinimumQuantity, OrderMaximumQuantity = productVariant.OrderMaximumQuantity, AllowedQuantities = productVariant.AllowedQuantities, DisableBuyButton = productVariant.DisableBuyButton, DisableWishlistButton = productVariant.DisableWishlistButton, CallForPrice = productVariant.CallForPrice, Price = productVariant.Price, OldPrice = productVariant.OldPrice, ProductCost = productVariant.ProductCost, SpecialPrice = productVariant.SpecialPrice, SpecialPriceStartDateTimeUtc = productVariant.SpecialPriceStartDateTimeUtc, SpecialPriceEndDateTimeUtc = productVariant.SpecialPriceEndDateTimeUtc, CustomerEntersPrice = productVariant.CustomerEntersPrice, MinimumCustomerEnteredPrice = productVariant.MinimumCustomerEnteredPrice, MaximumCustomerEnteredPrice = productVariant.MaximumCustomerEnteredPrice, Weight = productVariant.Weight, Length = productVariant.Length, Width = productVariant.Width, Height = productVariant.Height, PictureId = pictureId, AvailableStartDateTimeUtc = productVariant.AvailableStartDateTimeUtc, AvailableEndDateTimeUtc = productVariant.AvailableEndDateTimeUtc, Published = productVariant.Published, Deleted = productVariant.Deleted, DisplayOrder = productVariant.DisplayOrder, CreatedOnUtc = DateTime.UtcNow, UpdatedOnUtc = DateTime.UtcNow }; _productService.InsertProductVariant(productVariantCopy); //localization foreach (var lang in languages) { var name = productVariant.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(productVariantCopy, x => x.Name, name, lang.Id); var description = productVariant.GetLocalized(x => x.Description, lang.Id, false, false); if (!String.IsNullOrEmpty(description)) _localizedEntityService.SaveLocalizedValue(productVariantCopy, x => x.Description, description, lang.Id); } // product variant <-> attributes mappings var associatedAttributes = new Dictionary<int, int>(); var associatedAttributeValues = new Dictionary<int, int>(); foreach (var productVariantAttribute in _productAttributeService.GetProductVariantAttributesByProductVariantId(productVariant.Id)) { var productVariantAttributeCopy = new ProductVariantAttribute() { ProductVariantId = productVariantCopy.Id, ProductAttributeId = productVariantAttribute.ProductAttributeId, TextPrompt = productVariantAttribute.TextPrompt, IsRequired = productVariantAttribute.IsRequired, AttributeControlTypeId = productVariantAttribute.AttributeControlTypeId, DisplayOrder = productVariantAttribute.DisplayOrder }; _productAttributeService.InsertProductVariantAttribute(productVariantAttributeCopy); //save associated value (used for combinations copying) associatedAttributes.Add(productVariantAttribute.Id, productVariantAttributeCopy.Id); // product variant attribute values var productVariantAttributeValues = _productAttributeService.GetProductVariantAttributeValues(productVariantAttribute.Id); foreach (var productVariantAttributeValue in productVariantAttributeValues) { var pvavCopy = new ProductVariantAttributeValue() { ProductVariantAttributeId = productVariantAttributeCopy.Id, Name = productVariantAttributeValue.Name, PriceAdjustment = productVariantAttributeValue.PriceAdjustment, WeightAdjustment = productVariantAttributeValue.WeightAdjustment, IsPreSelected = productVariantAttributeValue.IsPreSelected, DisplayOrder = productVariantAttributeValue.DisplayOrder }; _productAttributeService.InsertProductVariantAttributeValue(pvavCopy); //save associated value (used for combinations copying) associatedAttributeValues.Add(productVariantAttributeValue.Id, pvavCopy.Id); //localization foreach (var lang in languages) { var name = productVariantAttributeValue.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(pvavCopy, x => x.Name, name, lang.Id); } } } foreach (var combination in _productAttributeService.GetAllProductVariantAttributeCombinations(productVariant.Id)) { //generate new AttributesXml according to new value IDs string newAttributesXml = ""; var parsedProductVariantAttributes = _productAttributeParser.ParseProductVariantAttributes(combination.AttributesXml); foreach (var oldPva in parsedProductVariantAttributes) { if (associatedAttributes.ContainsKey(oldPva.Id)) { int newPvaId = associatedAttributes[oldPva.Id]; var newPva = _productAttributeService.GetProductVariantAttributeById(newPvaId); if (newPva != null) { var oldPvaValuesStr = _productAttributeParser.ParseValues(combination.AttributesXml, oldPva.Id); foreach (var oldPvaValueStr in oldPvaValuesStr) { if (newPva.ShouldHaveValues()) { //attribute values int oldPvaValue = int.Parse(oldPvaValueStr); if (associatedAttributeValues.ContainsKey(oldPvaValue)) { int newPvavId = associatedAttributeValues[oldPvaValue]; var newPvav = _productAttributeService.GetProductVariantAttributeValueById(newPvavId); if (newPvav != null) { newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, newPvav.Id.ToString()); } } } else { //just a text newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, oldPvaValueStr); } } } } } var combinationCopy = new ProductVariantAttributeCombination() { ProductVariantId = productVariantCopy.Id, AttributesXml = newAttributesXml, StockQuantity = combination.StockQuantity, AllowOutOfStockOrders = combination.AllowOutOfStockOrders }; _productAttributeService.InsertProductVariantAttributeCombination(combinationCopy); } // product variant tier prices foreach (var tierPrice in productVariant.TierPrices) { _productService.InsertTierPrice( new TierPrice() { ProductVariantId = productVariantCopy.Id, CustomerRoleId = tierPrice.CustomerRoleId, Quantity = tierPrice.Quantity, Price = tierPrice.Price }); } // product variant <-> discounts mapping foreach (var discount in productVariant.AppliedDiscounts) { productVariantCopy.AppliedDiscounts.Add(discount); _productService.UpdateProductVariant(productVariantCopy); } //update "HasTierPrices" and "HasDiscountsApplied" properties _productService.UpdateHasTierPricesProperty(productVariantCopy); _productService.UpdateHasDiscountsApplied(productVariantCopy); } //uncomment this line to support transactions //scope.Complete(); } return productCopy; }
protected virtual void UpdateLocales(ProductVariantAttributeValue pvav, ProductModel.ProductVariantAttributeValueModel model) { foreach (var localized in model.Locales) { _localizedEntityService.SaveLocalizedValue(pvav, x => x.Name, localized.Name, localized.LanguageId); } }
public ActionResult ProductAttributeValueCreatePopup(string btnId, string formId, ProductModel.ProductVariantAttributeValueModel model) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts)) return AccessDeniedView(); var pva = _productAttributeService.GetProductVariantAttributeById(model.ProductVariantAttributeId); if (pva == null) //No product variant attribute found with the specified id return RedirectToAction("List", "Product"); var product = _productService.GetProductById(pva.ProductId); if (product == null) throw new ArgumentException("No product found with the specified id"); //a vendor should have access only to his products if (_workContext.CurrentVendor != null&& product.VendorId != _workContext.CurrentVendor.Id) return RedirectToAction("List", "Product"); if (pva.AttributeControlType == AttributeControlType.ColorSquares) { //ensure valid color is chosen/entered if (String.IsNullOrEmpty(model.ColorSquaresRgb)) ModelState.AddModelError("", "Color is required"); try { var color = System.Drawing.ColorTranslator.FromHtml(model.ColorSquaresRgb); } catch (Exception exc) { ModelState.AddModelError("", exc.Message); } } if (ModelState.IsValid) { var pvav = new ProductVariantAttributeValue() { ProductVariantAttributeId = model.ProductVariantAttributeId, AttributeValueTypeId = model.AttributeValueTypeId, AssociatedProductId = model.AssociatedProductId, Name = model.Name, ColorSquaresRgb = model.ColorSquaresRgb, PriceAdjustment = model.PriceAdjustment, WeightAdjustment = model.WeightAdjustment, Cost = model.Cost, Quantity = model.Quantity, IsPreSelected = model.IsPreSelected, DisplayOrder = model.DisplayOrder, PictureId = model.PictureId, }; _productAttributeService.InsertProductVariantAttributeValue(pvav); UpdateLocales(pvav, model); ViewBag.RefreshPage = true; ViewBag.btnId = btnId; ViewBag.formId = formId; return View(model); } //If we got this far, something failed, redisplay form //pictures model.ProductPictureModels = _productService.GetProductPicturesByProductId(product.Id) .Select(x => { return new ProductModel.ProductPictureModel() { Id = x.Id, ProductId = x.ProductId, PictureId = x.PictureId, PictureUrl = _pictureService.GetPictureUrl(x.PictureId), DisplayOrder = x.DisplayOrder }; }) .ToList(); var associatedProduct = _productService.GetProductById(model.AssociatedProductId); model.AssociatedProductName = associatedProduct != null ? associatedProduct.Name : ""; return View(model); }
public new void SetUp() { #region Test data //color (dropdownlist) pa1 = new ProductAttribute { Id = 1, Name = "Color", }; pva1_1 = new ProductVariantAttribute { Id = 11, ProductId = 1, TextPrompt = "Select color:", IsRequired = true, AttributeControlType = AttributeControlType.DropdownList, DisplayOrder = 1, ProductAttribute = pa1, ProductAttributeId = pa1.Id }; pvav1_1 = new ProductVariantAttributeValue { Id = 11, Name = "Green", DisplayOrder = 1, ProductVariantAttribute = pva1_1, ProductVariantAttributeId = pva1_1.Id }; pvav1_2 = new ProductVariantAttributeValue { Id = 12, Name = "Red", DisplayOrder = 2, ProductVariantAttribute = pva1_1, ProductVariantAttributeId = pva1_1.Id }; pva1_1.ProductVariantAttributeValues.Add(pvav1_1); pva1_1.ProductVariantAttributeValues.Add(pvav1_2); //custom option (checkboxes) pa2 = new ProductAttribute { Id = 2, Name = "Some custom option", }; pva2_1 = new ProductVariantAttribute { Id = 21, ProductId = 1, TextPrompt = "Select at least one option:", IsRequired = true, AttributeControlType = AttributeControlType.Checkboxes, DisplayOrder = 2, ProductAttribute = pa2, ProductAttributeId = pa2.Id }; pvav2_1 = new ProductVariantAttributeValue { Id = 21, Name = "Option 1", DisplayOrder = 1, ProductVariantAttribute = pva2_1, ProductVariantAttributeId = pva2_1.Id }; pvav2_2 = new ProductVariantAttributeValue { Id = 22, Name = "Option 2", DisplayOrder = 2, ProductVariantAttribute = pva2_1, ProductVariantAttributeId = pva2_1.Id }; pva2_1.ProductVariantAttributeValues.Add(pvav2_1); pva2_1.ProductVariantAttributeValues.Add(pvav2_2); //custom text pa3 = new ProductAttribute { Id = 3, Name = "Custom text", }; pva3_1 = new ProductVariantAttribute { Id = 31, ProductId = 1, TextPrompt = "Enter custom text:", IsRequired = true, AttributeControlType = AttributeControlType.TextBox, DisplayOrder = 1, ProductAttribute = pa1, ProductAttributeId = pa3.Id }; #endregion _productAttributeRepo = MockRepository.GenerateMock<IRepository<ProductAttribute>>(); _productAttributeRepo.Expect(x => x.Table).Return(new List<ProductAttribute>() { pa1, pa2, pa3 }.AsQueryable()); _productAttributeRepo.Expect(x => x.GetById(pa1.Id)).Return(pa1); _productAttributeRepo.Expect(x => x.GetById(pa2.Id)).Return(pa2); _productAttributeRepo.Expect(x => x.GetById(pa3.Id)).Return(pa3); _productVariantAttributeRepo = MockRepository.GenerateMock<IRepository<ProductVariantAttribute>>(); _productVariantAttributeRepo.Expect(x => x.Table).Return(new List<ProductVariantAttribute>() { pva1_1, pva2_1, pva3_1 }.AsQueryable()); _productVariantAttributeRepo.Expect(x => x.GetById(pva1_1.Id)).Return(pva1_1); _productVariantAttributeRepo.Expect(x => x.GetById(pva2_1.Id)).Return(pva2_1); _productVariantAttributeRepo.Expect(x => x.GetById(pva3_1.Id)).Return(pva3_1); _productVariantAttributeCombinationRepo = MockRepository.GenerateMock<IRepository<ProductVariantAttributeCombination>>(); _productVariantAttributeCombinationRepo.Expect(x => x.Table).Return(new List<ProductVariantAttributeCombination>().AsQueryable()); _productVariantAttributeValueRepo = MockRepository.GenerateMock<IRepository<ProductVariantAttributeValue>>(); _productVariantAttributeValueRepo.Expect(x => x.Table).Return(new List<ProductVariantAttributeValue>() { pvav1_1, pvav1_2, pvav2_1, pvav2_2 }.AsQueryable()); _productVariantAttributeValueRepo.Expect(x => x.GetById(pvav1_1.Id)).Return(pvav1_1); _productVariantAttributeValueRepo.Expect(x => x.GetById(pvav1_2.Id)).Return(pvav1_2); _productVariantAttributeValueRepo.Expect(x => x.GetById(pvav2_1.Id)).Return(pvav2_1); _productVariantAttributeValueRepo.Expect(x => x.GetById(pvav2_2.Id)).Return(pvav2_2); _eventPublisher = MockRepository.GenerateMock<IEventPublisher>(); _eventPublisher.Expect(x => x.Publish(Arg<object>.Is.Anything)); var cacheManager = new NopNullCache(); _productAttributeService = new ProductAttributeService(cacheManager, _productAttributeRepo, _productVariantAttributeRepo, _productVariantAttributeCombinationRepo, _productVariantAttributeValueRepo, _eventPublisher); _productAttributeParser = new ProductAttributeParser(_productAttributeService); _priceCalculationService = MockRepository.GenerateMock<IPriceCalculationService>(); var workingLanguage = new Language(); _workContext = MockRepository.GenerateMock<IWorkContext>(); _workContext.Expect(x => x.WorkingLanguage).Return(workingLanguage); _currencyService = MockRepository.GenerateMock<ICurrencyService>(); _localizationService = MockRepository.GenerateMock<ILocalizationService>(); _localizationService.Expect(x => x.GetResource("GiftCardAttribute.For.Virtual")).Return("For: {0} <{1}>"); _localizationService.Expect(x => x.GetResource("GiftCardAttribute.From.Virtual")).Return("From: {0} <{1}>"); _localizationService.Expect(x => x.GetResource("GiftCardAttribute.For.Physical")).Return("For: {0}"); _localizationService.Expect(x => x.GetResource("GiftCardAttribute.From.Physical")).Return("From: {0}"); _taxService = MockRepository.GenerateMock<ITaxService>(); _priceFormatter = MockRepository.GenerateMock<IPriceFormatter>(); _downloadService = MockRepository.GenerateMock<IDownloadService>(); _webHelper = MockRepository.GenerateMock<IWebHelper>(); _productAttributeFormatter = new ProductAttributeFormatter(_workContext, _productAttributeService, _productAttributeParser, _currencyService, _localizationService, _taxService, _priceFormatter, _downloadService, _webHelper, _priceCalculationService); }
private void SaveVariant(Product product, ProductCreationModel model) { // Update list of product pictures foreach (string pictureID in model.pictureIDs.Split(',')) { if (pictureID != "" && pictureID != "0") { int PictureID = Convert.ToInt32(pictureID); if (product.ProductPictures.Where(x => x.PictureId == PictureID).Count() <= 0) { } } } foreach (var x in product.ProductPictures.ToList()) { if (model.pictureIDs.Contains(x.PictureId.ToString()) == false) { ProductPictureDelete(x.Id); } } List<ProductVariantDTO> variantObj = JsonConvert.DeserializeObject<List<ProductVariantDTO>>(model.variantTransfer); List<string> AttributeDTOList = new List<string>(); var AllProductAttributes = _productAttributeService.GetAllProductAttributes(); //get all possible attributes for incoming DTO foreach (var variant in variantObj) { foreach (var combination in variant.combinations) { if (AttributeDTOList.Where(x => x == combination.attribute).Count() == 0) { AttributeDTOList.Add(combination.attribute); } } } //get existing product variant attributes var attlist = ProductVariantAttributeListobj(new DataSourceRequest(), product.Id); var pvaValList = new List<ProductVariantAttributeValue>(); //delete all existing pva values foreach (var pva in attlist) { var pvavalues = _productAttributeService.GetProductVariantAttributeValues(pva.Id); foreach (var pvaval in pvavalues) { _productAttributeService.DeleteProductVariantAttributeValue(pvaval); } } //make sure all pvas are mapped foreach (var attribute in AttributeDTOList) { bool wasfound = false; foreach (var pva in attlist) { if (pva.ProductAttribute == attribute) { wasfound = true; } } //if not found insert new product variant attribute if (wasfound == false) { Nop.Admin.Models.Catalog.ProductModel.ProductVariantAttributeModel newPva = new Nop.Admin.Models.Catalog.ProductModel.ProductVariantAttributeModel(); var combo = variantObj.Where(x => x.combinations.Where(y => y.attribute == attribute).Count() == 1).Single(); newPva.ProductId = product.Id; newPva.ProductAttribute = attribute; newPva.IsRequired = true; newPva.TextPrompt = combo.combinations.Where(z => z.attribute == attribute).Single().textPrompt; newPva.ProductAttributeId = AllProductAttributes.Where(att => att.Name == attribute).Select(x => x.Id).Single(); ProductVariantAttributeInsert(newPva); } } //todo insert pva values for each combination in the dto for each variant var variantAttributeList = _productAttributeService.GetProductVariantAttributesByProductId(product.Id); foreach (var variant in variantAttributeList) { //variants from the dto that have this variant attribute/product attribute var obj = variantObj.Where(x => x.combinations.Where(y => y.attribute == variant.ProductAttribute.Name).Count() > 0); foreach (var dtovariant in obj) { var pvav = new ProductVariantAttributeValue() { ProductVariantAttributeId = variant.Id, AssociatedProductId = variant.ProductId, Name = variant.ProductAttribute.Name, PriceAdjustment = dtovariant.priceAdjustment, Cost = product.ProductCost, Quantity = dtovariant.quantity, IsPreSelected = true, }; _productAttributeService.InsertProductVariantAttributeValue(pvav); } } //Once all new product variant attribute values are in place generate combinations and substitue DTO data var allAttributesXml = _productAttributeParser.GenerateAllCombinations(product); foreach (var attributesXml in allAttributesXml) { var existingCombination = _productAttributeParser.FindProductVariantAttributeCombination(product, attributesXml); //already exists? if (existingCombination != null) continue; //new one var warnings = new List<string>(); warnings.AddRange(_shoppingCartService.GetShoppingCartItemAttributeWarnings(_workContext.CurrentCustomer, ShoppingCartType.ShoppingCart, product, 1, attributesXml)); if (warnings.Count != 0) continue; //save combination var combination = new ProductVariantAttributeCombination() { ProductId = product.Id, AttributesXml = attributesXml, StockQuantity = 10000, AllowOutOfStockOrders = false, Sku = null, ManufacturerPartNumber = null, Gtin = null, OverriddenPrice = null }; _productAttributeService.InsertProductVariantAttributeCombination(combination); } }
/// <summary> /// Create a copy of product with all depended data /// </summary> /// <param name="product">The product to copy</param> /// <param name="newName">The name of product duplicate</param> /// <param name="isPublished">A value indicating whether the product duplicate should be published</param> /// <param name="copyImages">A value indicating whether the product images should be copied</param> /// <param name="copyAssociatedProducts">A value indicating whether the copy associated products</param> /// <returns>Product copy</returns> public virtual Product CopyProduct(Product product, string newName, bool isPublished = true, bool copyImages = true, bool copyAssociatedProducts = true) { if (product == null) throw new ArgumentNullException("product"); if (String.IsNullOrEmpty(newName)) throw new ArgumentException("Product name is required"); Product productCopy = null; //product download & sample download int downloadId = product.DownloadId; int sampleDownloadId = product.SampleDownloadId; if (product.IsDownload) { var download = _downloadService.GetDownloadById(product.DownloadId); if (download != null) { var downloadCopy = new Download() { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = download.UseDownloadUrl, DownloadUrl = download.DownloadUrl, DownloadBinary = download.DownloadBinary, ContentType = download.ContentType, Filename = download.Filename, Extension = download.Extension, IsNew = download.IsNew, }; _downloadService.InsertDownload(downloadCopy); downloadId = downloadCopy.Id; } if (product.HasSampleDownload) { var sampleDownload = _downloadService.GetDownloadById(product.SampleDownloadId); if (sampleDownload != null) { var sampleDownloadCopy = new Download() { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = sampleDownload.UseDownloadUrl, DownloadUrl = sampleDownload.DownloadUrl, DownloadBinary = sampleDownload.DownloadBinary, ContentType = sampleDownload.ContentType, Filename = sampleDownload.Filename, Extension = sampleDownload.Extension, IsNew = sampleDownload.IsNew }; _downloadService.InsertDownload(sampleDownloadCopy); sampleDownloadId = sampleDownloadCopy.Id; } } } // product productCopy = new Product() { ProductTypeId = product.ProductTypeId, ParentGroupedProductId = product.ParentGroupedProductId, VisibleIndividually = product.VisibleIndividually, Name = newName, ShortDescription = product.ShortDescription, FullDescription = product.FullDescription, VendorId = product.VendorId, ProductTemplateId = product.ProductTemplateId, AdminComment = product.AdminComment, ShowOnHomePage = product.ShowOnHomePage, MetaKeywords = product.MetaKeywords, MetaDescription = product.MetaDescription, MetaTitle = product.MetaTitle, AllowCustomerReviews = product.AllowCustomerReviews, LimitedToStores = product.LimitedToStores, Sku = product.Sku, ManufacturerPartNumber = product.ManufacturerPartNumber, Gtin = product.Gtin, IsGiftCard = product.IsGiftCard, GiftCardType = product.GiftCardType, FirstCostCurrencyType = product.FirstCostCurrencyType, RequireOtherProducts = product.RequireOtherProducts, RequiredProductIds = product.RequiredProductIds, AutomaticallyAddRequiredProducts = product.AutomaticallyAddRequiredProducts, IsDownload = product.IsDownload, DownloadId = downloadId, UnlimitedDownloads = product.UnlimitedDownloads, MaxNumberOfDownloads = product.MaxNumberOfDownloads, DownloadExpirationDays = product.DownloadExpirationDays, DownloadActivationType = product.DownloadActivationType, HasSampleDownload = product.HasSampleDownload, SampleDownloadId = sampleDownloadId, HasUserAgreement = product.HasUserAgreement, UserAgreementText = product.UserAgreementText, IsRecurring = product.IsRecurring, RecurringCycleLength = product.RecurringCycleLength, RecurringCyclePeriod = product.RecurringCyclePeriod, RecurringTotalCycles = product.RecurringTotalCycles, IsShipEnabled = product.IsShipEnabled, IsFreeShipping = product.IsFreeShipping, AdditionalShippingCharge = product.AdditionalShippingCharge, DeliveryDateId = product.DeliveryDateId, WarehouseId = product.WarehouseId, IsTaxExempt = product.IsTaxExempt, TaxCategoryId = product.TaxCategoryId, ManageInventoryMethod = product.ManageInventoryMethod, StockQuantity = product.StockQuantity, DisplayStockAvailability = product.DisplayStockAvailability, DisplayStockQuantity = product.DisplayStockQuantity, MinStockQuantity = product.MinStockQuantity, LowStockActivityId = product.LowStockActivityId, NotifyAdminForQuantityBelow = product.NotifyAdminForQuantityBelow, BackorderMode = product.BackorderMode, AllowBackInStockSubscriptions = product.AllowBackInStockSubscriptions, OrderMinimumQuantity = product.OrderMinimumQuantity, OrderMaximumQuantity = product.OrderMaximumQuantity, AllowedQuantities = product.AllowedQuantities, AllowAddingOnlyExistingAttributeCombinations = product.AllowAddingOnlyExistingAttributeCombinations, DisableBuyButton = product.DisableBuyButton, DisableWishlistButton = product.DisableWishlistButton, AvailableForPreOrder = product.AvailableForPreOrder, PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc, CallForPrice = product.CallForPrice, Price = product.Price, FirstCost = product.FirstCost, DollarPrice = product.DollarPrice, DesiredProfit = product.DesiredProfit, OldPrice = product.OldPrice, ProductCost = product.ProductCost, SpecialPrice = product.SpecialPrice, SpecialPriceStartDateTimeUtc = product.SpecialPriceStartDateTimeUtc, SpecialPriceEndDateTimeUtc = product.SpecialPriceEndDateTimeUtc, CustomerEntersPrice = product.CustomerEntersPrice, MinimumCustomerEnteredPrice = product.MinimumCustomerEnteredPrice, MaximumCustomerEnteredPrice = product.MaximumCustomerEnteredPrice, Weight = product.Weight, Length = product.Length, Width = product.Width, Height = product.Height, AvailableStartDateTimeUtc = product.AvailableStartDateTimeUtc, AvailableEndDateTimeUtc = product.AvailableEndDateTimeUtc, DisplayOrder = product.DisplayOrder, Published = isPublished, Deleted = product.Deleted, CreatedOnUtc = DateTime.UtcNow, UpdatedOnUtc = DateTime.UtcNow }; //validate search engine name _productService.InsertProduct(productCopy); //search engine name _urlRecordService.SaveSlug(productCopy, productCopy.ValidateSeName("", productCopy.Name, true), 0); var languages = _languageService.GetAllLanguages(true); //localization foreach (var lang in languages) { var name = product.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.Name, name, lang.Id); var shortDescription = product.GetLocalized(x => x.ShortDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(shortDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.ShortDescription, shortDescription, lang.Id); var fullDescription = product.GetLocalized(x => x.FullDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(fullDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.FullDescription, fullDescription, lang.Id); var metaKeywords = product.GetLocalized(x => x.MetaKeywords, lang.Id, false, false); if (!String.IsNullOrEmpty(metaKeywords)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaKeywords, metaKeywords, lang.Id); var metaDescription = product.GetLocalized(x => x.MetaDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(metaDescription)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaDescription, metaDescription, lang.Id); var metaTitle = product.GetLocalized(x => x.MetaTitle, lang.Id, false, false); if (!String.IsNullOrEmpty(metaTitle)) _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaTitle, metaTitle, lang.Id); //search engine name _urlRecordService.SaveSlug(productCopy, productCopy.ValidateSeName("", name, false), lang.Id); } //product tags foreach (var productTag in product.ProductTags) { productCopy.ProductTags.Add(productTag); } _productService.UpdateProduct(product); // product pictures //variant to store original and new picture identifiers var originalNewPictureIdentifiers = new Dictionary<int, int>(); if (copyImages) { foreach (var productPicture in product.ProductPictures) { var picture = productPicture.Picture; var pictureCopy = _pictureService.InsertPicture( _pictureService.LoadPictureBinary(picture), picture.MimeType, _pictureService.GetPictureSeName(newName), true); _productService.InsertProductPicture(new ProductPicture() { ProductId = productCopy.Id, PictureId = pictureCopy.Id, DisplayOrder = productPicture.DisplayOrder }); originalNewPictureIdentifiers.Add(picture.Id, pictureCopy.Id); } } // product <-> categories mappings foreach (var productCategory in product.ProductCategories) { var productCategoryCopy = new ProductCategory() { ProductId = productCopy.Id, CategoryId = productCategory.CategoryId, IsFeaturedProduct = productCategory.IsFeaturedProduct, DisplayOrder = productCategory.DisplayOrder }; _categoryService.InsertProductCategory(productCategoryCopy); } // product <-> manufacturers mappings foreach (var productManufacturers in product.ProductManufacturers) { var productManufacturerCopy = new ProductManufacturer() { ProductId = productCopy.Id, ManufacturerId = productManufacturers.ManufacturerId, IsFeaturedProduct = productManufacturers.IsFeaturedProduct, DisplayOrder = productManufacturers.DisplayOrder }; _manufacturerService.InsertProductManufacturer(productManufacturerCopy); } // product <-> releated products mappings foreach (var relatedProduct in _productService.GetRelatedProductsByProductId1(product.Id, true)) { _productService.InsertRelatedProduct( new RelatedProduct() { ProductId1 = productCopy.Id, ProductId2 = relatedProduct.ProductId2, DisplayOrder = relatedProduct.DisplayOrder }); } // product <-> cross sells mappings foreach (var csProduct in _productService.GetCrossSellProductsByProductId1(product.Id, true)) { _productService.InsertCrossSellProduct( new CrossSellProduct() { ProductId1 = productCopy.Id, ProductId2 = csProduct.ProductId2, }); } // product specifications foreach (var productSpecificationAttribute in product.ProductSpecificationAttributes) { var psaCopy = new ProductSpecificationAttribute() { ProductId = productCopy.Id, SpecificationAttributeOptionId = productSpecificationAttribute.SpecificationAttributeOptionId, CustomValue = productSpecificationAttribute.CustomValue, AllowFiltering = productSpecificationAttribute.AllowFiltering, ShowOnProductPage = productSpecificationAttribute.ShowOnProductPage, DisplayOrder = productSpecificationAttribute.DisplayOrder }; _specificationAttributeService.InsertProductSpecificationAttribute(psaCopy); } //store mapping var selectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(product); foreach (var id in selectedStoreIds) { _storeMappingService.InsertStoreMapping(productCopy, id); } // product <-> attributes mappings var associatedAttributes = new Dictionary<int, int>(); var associatedAttributeValues = new Dictionary<int, int>(); foreach (var productVariantAttribute in _productAttributeService.GetProductVariantAttributesByProductId(product.Id)) { var productVariantAttributeCopy = new ProductVariantAttribute() { ProductId = productCopy.Id, ProductAttributeId = productVariantAttribute.ProductAttributeId, TextPrompt = productVariantAttribute.TextPrompt, IsRequired = productVariantAttribute.IsRequired, AttributeControlTypeId = productVariantAttribute.AttributeControlTypeId, DisplayOrder = productVariantAttribute.DisplayOrder, ValidationMinLength = productVariantAttribute.ValidationMinLength, ValidationMaxLength = productVariantAttribute.ValidationMaxLength, ValidationFileAllowedExtensions = productVariantAttribute.ValidationFileAllowedExtensions, ValidationFileMaximumSize = productVariantAttribute.ValidationFileMaximumSize, DefaultValue = productVariantAttribute.DefaultValue, }; _productAttributeService.InsertProductVariantAttribute(productVariantAttributeCopy); //save associated value (used for combinations copying) associatedAttributes.Add(productVariantAttribute.Id, productVariantAttributeCopy.Id); // product variant attribute values var productVariantAttributeValues = _productAttributeService.GetProductVariantAttributeValues(productVariantAttribute.Id); foreach (var productVariantAttributeValue in productVariantAttributeValues) { int pvavPictureId = 0; if (originalNewPictureIdentifiers.ContainsKey(productVariantAttributeValue.PictureId)) { pvavPictureId = originalNewPictureIdentifiers[productVariantAttributeValue.PictureId]; } var pvavCopy = new ProductVariantAttributeValue() { ProductVariantAttributeId = productVariantAttributeCopy.Id, AttributeValueTypeId = productVariantAttributeValue.AttributeValueTypeId, AssociatedProductId = productVariantAttributeValue.AssociatedProductId, Name = productVariantAttributeValue.Name, ColorSquaresRgb = productVariantAttributeValue.ColorSquaresRgb, PriceAdjustment = productVariantAttributeValue.PriceAdjustment, WeightAdjustment = productVariantAttributeValue.WeightAdjustment, Cost = productVariantAttributeValue.Cost, Quantity = productVariantAttributeValue.Quantity, IsPreSelected = productVariantAttributeValue.IsPreSelected, DisplayOrder = productVariantAttributeValue.DisplayOrder, PictureId = pvavPictureId, }; _productAttributeService.InsertProductVariantAttributeValue(pvavCopy); //save associated value (used for combinations copying) associatedAttributeValues.Add(productVariantAttributeValue.Id, pvavCopy.Id); //localization foreach (var lang in languages) { var name = productVariantAttributeValue.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) _localizedEntityService.SaveLocalizedValue(pvavCopy, x => x.Name, name, lang.Id); } } } //attribute combinations foreach (var combination in _productAttributeService.GetAllProductVariantAttributeCombinations(product.Id)) { //generate new AttributesXml according to new value IDs string newAttributesXml = ""; var parsedProductVariantAttributes = _productAttributeParser.ParseProductVariantAttributes(combination.AttributesXml); foreach (var oldPva in parsedProductVariantAttributes) { if (associatedAttributes.ContainsKey(oldPva.Id)) { int newPvaId = associatedAttributes[oldPva.Id]; var newPva = _productAttributeService.GetProductVariantAttributeById(newPvaId); if (newPva != null) { var oldPvaValuesStr = _productAttributeParser.ParseValues(combination.AttributesXml, oldPva.Id); foreach (var oldPvaValueStr in oldPvaValuesStr) { if (newPva.ShouldHaveValues()) { //attribute values int oldPvaValue = int.Parse(oldPvaValueStr); if (associatedAttributeValues.ContainsKey(oldPvaValue)) { int newPvavId = associatedAttributeValues[oldPvaValue]; var newPvav = _productAttributeService.GetProductVariantAttributeValueById(newPvavId); if (newPvav != null) { newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, newPvav.Id.ToString()); } } } else { //just a text newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, oldPvaValueStr); } } } } } var combinationCopy = new ProductVariantAttributeCombination() { ProductId = productCopy.Id, AttributesXml = newAttributesXml, StockQuantity = combination.StockQuantity, AllowOutOfStockOrders = combination.AllowOutOfStockOrders, Sku = combination.Sku, ManufacturerPartNumber = combination.ManufacturerPartNumber, Gtin = combination.Gtin, OverriddenPrice = combination.OverriddenPrice }; _productAttributeService.InsertProductVariantAttributeCombination(combinationCopy); } //tier prices foreach (var tierPrice in product.TierPrices) { _productService.InsertTierPrice( new TierPrice() { ProductId = productCopy.Id, StoreId = tierPrice.StoreId, CustomerRoleId = tierPrice.CustomerRoleId, Quantity = tierPrice.Quantity, Price = tierPrice.Price }); } // product <-> discounts mapping foreach (var discount in product.AppliedDiscounts) { productCopy.AppliedDiscounts.Add(discount); _productService.UpdateProduct(productCopy); } //update "HasTierPrices" and "HasDiscountsApplied" properties _productService.UpdateHasTierPricesProperty(productCopy); _productService.UpdateHasDiscountsApplied(productCopy); //associated products if (copyAssociatedProducts) { var associatedProducts = _productService.GetAssociatedProducts(product.Id, showHidden: true); foreach (var associatedProduct in associatedProducts) { var associatedProductCopy = CopyProduct(associatedProduct, string.Format("Copy of {0}", associatedProduct.Name), isPublished, copyImages, false); associatedProductCopy.ParentGroupedProductId = productCopy.Id; _productService.UpdateProduct(productCopy); } } return productCopy; }