internal static void Import(КоммерческаяИнформация source, IShippingService shippingService, IDbContext dbContext, string warehouseMappingsFile, string mappingsFile, string logFile) { var warehouseMappings = ImportWarehouses(source, shippingService, warehouseMappingsFile, logFile); ImportOffers(source, dbContext, warehouseMappings, mappingsFile, logFile); }
/// <summary> /// Импорт предложений /// </summary> /// <param name="logFile"></param> /// <param name="dir"></param> /// <param name="source"></param> private void ImportOffers(string logFile, string dir, КоммерческаяИнформация source) { XmlOffersImportService.Import(source, _shippingService, _dbContext, $"{dir}\\WarehouseMappings.json", $"{dir}\\ProductsMappings.json", logFile); }
private static Dictionary <string, int> ImportWarehouses(КоммерческаяИнформация source, IShippingService shippingService, string warehouseMappingsFile, string logFile) { var stats = new[] { 0 }; logFile.Log("Начало импорта складов"); var warehouseMappings = File.Exists(warehouseMappingsFile) ? JsonConvert.DeserializeObject <Dictionary <string, int> >(File.ReadAllText(warehouseMappingsFile)) : new Dictionary <string, int>(); //todo: скорее всего класс изменится, когда будет больше складов, поэтому делаю коллекцию var whs = new[] { source.ПакетПредложений.Склады.Склад }.ToList(); var warehouses = shippingService.GetAllWarehouses(); foreach (var wh in whs) { if (!warehouseMappings.ContainsKey(wh.Ид) || warehouses.All(w => w.Id != warehouseMappings[wh.Ид])) { var warehouse = new Warehouse { Name = wh.Наименование, AdminComment = wh.Ид }; shippingService.InsertWarehouse(warehouse); warehouseMappings[wh.Ид] = warehouse.Id; stats[0]++; } } File.WriteAllText(warehouseMappingsFile, JsonConvert.SerializeObject(warehouseMappings, Formatting.Indented), Encoding.UTF8); logFile.Log($"Импорт складов завершен. Добавлено: {stats[0]}."); return(warehouseMappings); }
internal static List <Category> Import(КоммерческаяИнформация source, ICategoryService categoryService, IUrlRecordService urlRecordService, string mappingsFile, out Dictionary <string, int> outMappings, string logFile) { logFile.Log("Начало импорта категорий"); var stats = new[] { 0, 0 }; // key = 1c id, value = nopcommerce id var mappings = File.Exists(mappingsFile) ? JsonConvert.DeserializeObject <Dictionary <string, int> >(File.ReadAllText(mappingsFile)) : new Dictionary <string, int>(); var categories = categoryService.GetAllCategories(showHidden: true).ToList(); var rootCategory = source.Классификатор.Группы.Группа; var rootItem = GetCategoryItem(rootCategory); if (rootItem.Items != null) { foreach (var child in rootItem.Items) { ImportCategory(child, null, categoryService, urlRecordService, categories, mappings, stats, logFile); } } File.WriteAllText(mappingsFile, JsonConvert.SerializeObject(mappings, Formatting.Indented), Encoding.UTF8); logFile.Log($"Импорт категорий завершен. Привязано: {stats[0]}. Добавлено: {stats[1]}."); outMappings = mappings; return(categories); }
/// <summary> /// Импорт /// </summary> /// <param name="updateExisting">обновлять существующие товары или игнорировать</param> /// <param name="importSpecificationAttributes">импортировать атрибуты</param> /// <param name="overwriteCategories">перезаписывать существующие категории или игнорировать</param> /// <param name="overwriteManufacturers">перезаписывать существующих производителей или игнорировать</param> /// <param name="logFile"></param> /// <param name="dir"></param> /// <param name="source"></param> private void Import(bool updateExisting, bool importSpecificationAttributes, bool overwriteCategories, bool overwriteManufacturers, string logFile, string dir, КоммерческаяИнформация source) { // add categories Dictionary <string, int> categoryMappings; var categories = XmlCategoryImportService.Import( source, _categoryService, _urlRecordService, $"{dir}\\CategoryMappings.json", out categoryMappings, logFile); // add attributes Dictionary <string, int> attributesMappings; List <SpecificationAttribute> attributes; if (importSpecificationAttributes) { attributes = XmlSpecificationAttributesImportService.Import( source, _specificationAttributeService, $"{dir}\\SpecificationAttributesMappings.json", out attributesMappings, logFile); } else { attributesMappings = new Dictionary <string, int>(); attributes = new List <SpecificationAttribute>(); } // add manufacturers Dictionary <string, int> manufacturersMappings; var manufacturers = XmlManufacturerImportService.Import( source, _manufacturerService, _urlRecordService, $"{dir}\\ManufacturerMappings.json", out manufacturersMappings, logFile); XmlCatalogImportService.Import(source, _categoryService, _specificationAttributeService, _manufacturerService, _productService, _urlRecordService, _pictureService, categories, categoryMappings, attributes, attributesMappings, manufacturers, manufacturersMappings, $"{dir}\\ProductsMappings.json", logFile, new XmlCatalogImportService.ImportCatalogSettings { UpdateExisting = updateExisting, ImportSpecificationAttributes = importSpecificationAttributes, OverwriteCategories = overwriteCategories, OverwriteManufacturers = overwriteManufacturers }); logFile.Log("Импорт завершен"); }
internal static List <SpecificationAttribute> Import(КоммерческаяИнформация source, ISpecificationAttributeService specificationAttributeService, string mappingsFile, out Dictionary <string, int> outMappings, string logFile) { logFile.Log("Начало импорта свойств"); var stats = new[] { 0, 0, 0, 0 }; // attribute: key = 1c id, value = nopcommerce id // attribute value: key = <1c attribute id>.<1c value id>, value = nopcommerce id var mappings = File.Exists(mappingsFile) ? JsonConvert.DeserializeObject <Dictionary <string, int> >(File.ReadAllText(mappingsFile)) : new Dictionary <string, int>();; var attributes = specificationAttributeService.GetSpecificationAttributes().ToList(); foreach (var attr in source.Классификатор.Свойства) { // ищем соответствие только по маппингу // потому что может быть несколько атрибутов с одинаковым названием var attribute = mappings.ContainsKey(attr.Ид) ? attributes.FirstOrDefault(a => a.Id == mappings[attr.Ид]) : null; if (attribute != null) { // для существующего только добавляем новые значения if (attr.ТипЗначений == AttrTypeDictionary) { foreach (var attrOption in attr.ВариантыЗначений) { var key = $"{attr.Ид}.{attrOption.ИдЗначения}"; var option = mappings.ContainsKey(key) ? attribute.SpecificationAttributeOptions.FirstOrDefault(o => o.Id == mappings[key]) : null; if (option == null) { // ищем по имени option = attribute.SpecificationAttributeOptions.FirstOrDefault(o => o.Name == attrOption.Значение); if (option == null) { // добавляем новое значение option = new Core.Domain.Catalog.SpecificationAttributeOption { SpecificationAttributeId = attribute.Id, Name = attrOption.Значение }; specificationAttributeService.InsertSpecificationAttributeOption(option); attribute.SpecificationAttributeOptions.Add(option); //logFile.Log($"В существующий атрибут {attribute.Name} ({attribute.Id}) добавлено значение {option.Name}"); stats[0]++; } else { // мапим существующее значение //logFile.Log($"В существующем атрибуте {attribute.Name} ({attribute.Id}) добавлено сопоставление для значения {option.Name}"); stats[1]++; } mappings[key] = option.Id; } } } continue; } // new attribute attribute = new Core.Domain.Catalog.SpecificationAttribute { Name = attr.Наименование }; specificationAttributeService.InsertSpecificationAttribute(attribute); attributes.Add(attribute); mappings[attr.Ид] = attribute.Id; //logFile.Log($"Новый атрибут {attribute.Name} ({attribute.Id})"); stats[2]++; if (attr.ТипЗначений == AttrTypeDictionary) { foreach (var attrOption in attr.ВариантыЗначений) { var key = $"{attr.Ид}.{attrOption.ИдЗначения}"; var option = new Core.Domain.Catalog.SpecificationAttributeOption { SpecificationAttributeId = attribute.Id, Name = attrOption.Значение }; specificationAttributeService.InsertSpecificationAttributeOption(option); attribute.SpecificationAttributeOptions.Add(option); mappings[key] = option.Id; //logFile.Log($"В новый атрибут {attribute.Name} ({attribute.Id}) добавлено значение {option.Name}"); stats[3]++; } } else { var key = $"{attr.Ид}."; var option = new Core.Domain.Catalog.SpecificationAttributeOption { SpecificationAttributeId = attribute.Id, Name = string.Empty }; specificationAttributeService.InsertSpecificationAttributeOption(option); attribute.SpecificationAttributeOptions.Add(option); mappings[key] = option.Id; } } File.WriteAllText(mappingsFile, JsonConvert.SerializeObject(mappings, Formatting.Indented), Encoding.UTF8); logFile.Log($"Импорт свойств завершен. Привязано: {stats[0]} атрибутов и {stats[1]} значений. Добавлено: {stats[2]} атрибутов и {stats[3]} значений."); outMappings = mappings; return(attributes); }
internal static void Import(КоммерческаяИнформация source, ICategoryService categoryService, ISpecificationAttributeService specificationAttributeService, IManufacturerService manufacturerService, IProductService productService, IUrlRecordService urlRecordService, IPictureService pictureService, List <Category> categories, Dictionary <string, int> categoryMappings, List <SpecificationAttribute> attributes, Dictionary <string, int> attributesMappings, List <Manufacturer> manufacturers, Dictionary <string, int> manufacturersMappings, string mappingsFile, string logFile, ImportCatalogSettings importSettings) { logFile.Log("Начало импорта товаров"); var stats = new[] { 0, 0 }; var mappings = File.Exists(mappingsFile) ? JsonConvert.DeserializeObject <Dictionary <string, int> >(File.ReadAllText(mappingsFile)) : new Dictionary <string, int>(); foreach (var prod in source.Каталог.Товары) { try { var product = mappings.ContainsKey(prod.Ид) ? productService.GetProductById(mappings[prod.Ид]) : null; var deleted = prod.Статус == "Удален"; if (product == null) { product = new Product { CreatedOnUtc = DateTime.Now, UpdatedOnUtc = DateTime.Now, ProductType = ProductType.SimpleProduct, ProductTemplateId = 1, VisibleIndividually = true, Name = prod.Наименование, Sku = prod.Артикул, ShortDescription = prod.Описание, FullDescription = prod.Описание, AllowCustomerReviews = true, Deleted = deleted, Published = !deleted, OrderMinimumQuantity = 1, OrderMaximumQuantity = 10000 }; productService.InsertProduct(product); var seName = product.ValidateSeName(null, product.Name, true); urlRecordService.SaveSlug(product, seName, 0); //logFile.Log($"Новый товар {product.Name} ({product.Id}): {prod.Ид}"); stats[0]++; } else { if (!importSettings.UpdateExisting) { //logFile.Log($"Пропущен товар {product.Name} ({product.Id}): {prod.Ид}"); stats[1]++; continue; } product.UpdatedOnUtc = DateTime.Now; product.Deleted = deleted; product.Published = !deleted; productService.UpdateProduct(product); //logFile.Log($"Обновлен товар {product.Name} ({product.Id}): {prod.Ид}"); stats[1]++; } mappings[prod.Ид] = product.Id; if (importSettings.OverwriteManufacturers) { foreach (var manufacturer in product.ProductManufacturers.ToList()) { manufacturerService.DeleteProductManufacturer(manufacturer); } } if (prod.Изготовитель != null && manufacturersMappings.ContainsKey(prod.Изготовитель.Ид)) { var manufacturerId = manufacturersMappings[prod.Изготовитель.Ид]; var manufacturer = product.ProductManufacturers.FirstOrDefault(m => m.ManufacturerId == manufacturerId); if (manufacturer == null) { manufacturer = new ProductManufacturer { ProductId = product.Id, ManufacturerId = manufacturerId }; manufacturerService.InsertProductManufacturer(manufacturer); product.ProductManufacturers.Add(manufacturer); } } if (importSettings.OverwriteCategories) { foreach (var category in product.ProductCategories.ToList()) { categoryService.DeleteProductCategory(category); } } if (prod.Группы != null && categoryMappings.ContainsKey(prod.Группы.Ид)) { var categoryId = categoryMappings[prod.Группы.Ид]; var category = product.ProductCategories.FirstOrDefault(c => c.CategoryId == categoryId); if (category == null) { category = new ProductCategory { ProductId = product.Id, CategoryId = categoryId }; categoryService.InsertProductCategory(category); product.ProductCategories.Add(category); } } if (importSettings.ImportSpecificationAttributes && prod.ЗначенияСвойств != null) { foreach (var attr in prod.ЗначенияСвойств) { if (attributesMappings.ContainsKey(attr.Ид)) { var emptyOptionKey = $"{attr.Ид}."; if (attributesMappings.ContainsKey(emptyOptionKey)) { var option = product.ProductSpecificationAttributes .FirstOrDefault(a => a.SpecificationAttributeOptionId == attributesMappings[emptyOptionKey]); if (option == null) { option = new ProductSpecificationAttribute { ProductId = product.Id, ShowOnProductPage = true, AllowFiltering = false, SpecificationAttributeOptionId = attributesMappings[emptyOptionKey], AttributeType = SpecificationAttributeType.CustomText, CustomValue = attr.Значение }; specificationAttributeService.InsertProductSpecificationAttribute(option); product.ProductSpecificationAttributes.Add(option); } else if (option.CustomValue != attr.Значение) { option.CustomValue = attr.Значение; specificationAttributeService.UpdateProductSpecificationAttribute(option); } } else { var optionKey = $"{attr.Ид}.{attr.Значение}"; var option = product.ProductSpecificationAttributes .FirstOrDefault(o => o.SpecificationAttributeOptionId == attributesMappings[optionKey]); if (option == null) { var attribute = attributes.FirstOrDefault(a => a.Id == attributesMappings[attr.Ид]); var optionIds = attribute.SpecificationAttributeOptions.Select(o => o.Id); var options = product.ProductSpecificationAttributes .Where(a => optionIds.Contains(a.SpecificationAttributeOptionId)).ToList(); if (options != null && options.Count > 0) { foreach (var opt in options) { product.ProductSpecificationAttributes.Remove(opt); specificationAttributeService.DeleteProductSpecificationAttribute(opt); } } option = new ProductSpecificationAttribute { ProductId = product.Id, ShowOnProductPage = true, AllowFiltering = true, SpecificationAttributeOptionId = attributesMappings[optionKey], AttributeType = SpecificationAttributeType.Option }; specificationAttributeService.InsertProductSpecificationAttribute(option); product.ProductSpecificationAttributes.Add(option); } } } } } if (!string.IsNullOrEmpty(prod.Картинка)) { // todo: compare with existing images var picturePath = HttpContext.Current.Request.MapPath($"~/Content/{prod.Картинка}"); var picture = LoadPicture(pictureService, picturePath, product.Name); if (picture != null) { product.ProductPictures.Add(new ProductPicture { DisplayOrder = 1, PictureId = picture.Id, ProductId = product.Id }); } } File.WriteAllText(mappingsFile, JsonConvert.SerializeObject(mappings, Formatting.Indented), Encoding.UTF8); } catch (Exception ex) { logFile.Log($"Ошибка при обработке товара {prod.Ид} ({prod.Наименование}): {ex}"); } } logFile.Log($"Импорт товаров завершен. Добавлено: {stats[0]}. Обновлено: {stats[1]}."); }
internal static List <Manufacturer> Import(КоммерческаяИнформация source, IManufacturerService manufacturerService, IUrlRecordService urlRecordService, string mappingsFile, out Dictionary <string, int> outMappings, string logFile) { logFile.Log("Начало импорта производителей"); var stats = new[] { 0, 0 }; var mappings = File.Exists(mappingsFile) ? JsonConvert.DeserializeObject <Dictionary <string, int> >(File.ReadAllText(mappingsFile)) : new Dictionary <string, int>(); var manufacturers = manufacturerService.GetAllManufacturers(showHidden: true).ToList(); var sourceManufacturers = source.Каталог.Товары .Where(t => t.Изготовитель != null) .Select(t => new { Id = t.Изготовитель.Ид, Name = t.Изготовитель.Наименование }) .Distinct() .ToList(); foreach (var man in sourceManufacturers) { var manufacturer = mappings.ContainsKey(man.Id) ? manufacturers.FirstOrDefault(m => m.Id == mappings[man.Id]) : null; if (manufacturer == null) { manufacturer = manufacturers.FirstOrDefault(m => m.Name == man.Name && !mappings.ContainsValue(m.Id)); if (manufacturer == null) { manufacturer = new Manufacturer { Name = man.Name, CreatedOnUtc = DateTime.UtcNow, UpdatedOnUtc = DateTime.UtcNow, Published = true, PageSize = 6, PageSizeOptions = "6, 3, 9", AllowCustomersToSelectPageSize = true, ManufacturerTemplateId = 1 }; manufacturerService.InsertManufacturer(manufacturer); var seName = manufacturer.ValidateSeName(null, manufacturer.Name, true); urlRecordService.SaveSlug(manufacturer, seName, 0); manufacturers.Add(manufacturer); //logFile.Log($"Новый бренд {manufacturer.Name} ({manufacturer.Id}): {man.Id}"); stats[0]++; } else { //logFile.Log($"Существующий бренд {manufacturer.Name} ({manufacturer.Id}): {man.Id}"); stats[1]++; } mappings[man.Id] = manufacturer.Id; } } File.WriteAllText(mappingsFile, JsonConvert.SerializeObject(mappings, Formatting.Indented), Encoding.UTF8); logFile.Log($"Импорт производителей завершен. Привязано: {stats[1]}. Добавлено: {stats[0]}."); outMappings = mappings; return(manufacturers); }
private static void ImportOffers(КоммерческаяИнформация source, IDbContext dbContext, Dictionary <string, int> warehouseMappings, string mappingsFile, string logFile) { var stats = new[] { 0 }; logFile.Log("Начало импорта предложений"); var mappings = File.Exists(mappingsFile) ? JsonConvert.DeserializeObject <Dictionary <string, int> >(File.ReadAllText(mappingsFile)) : new Dictionary <string, int>(); var sitePrice = new[] { source.ПакетПредложений.ТипыЦен.ТипЦены }.ToList() .FirstOrDefault(t => t.Наименование == "Для сайта"); var sqlBuilder = new StringBuilder(); foreach (var offer in source.ПакетПредложений.Предложения) { // только те продукты, которые были ранее добавлены if (!mappings.ContainsKey(offer.Ид)) { continue; } var productId = mappings[offer.Ид]; //todo: скорее всего их будет потом несколько var whs = new[] { offer.Склад }.ToList(); var whId = 0; var quantity = 0; //todo: пока поддерживаем только 1 склад, потом нужно будет написать отдельный код для нескольких складов if (whs.Count > 0) { var wh = whs[0]; whId = warehouseMappings.ContainsKey(wh.ИдСклада) ? warehouseMappings[wh.ИдСклада] : 0; quantity = wh.КоличествоНаСкладе; } decimal price = 0; if (sitePrice != null) { var offerPrice = new[] { offer.Цены.Цена }.ToList().FirstOrDefault(p => p.ИдТипаЦены == sitePrice.Ид); if (offerPrice != null) { price = offerPrice.ЦенаЗаЕдиницу; } } stats[0]++; sqlBuilder.AppendLine($"UPDATE [{ProductTableName}] SET [WarehouseId]={whId}, [StockQuantity]={quantity}, [Price]={price.ToString(CultureInfo.InvariantCulture)} WHERE [Id]={productId};"); // выполняем обновление БД пакетами по <packageSize> штук const int packageSize = 1000; if (stats[0] % packageSize == 0) { try { dbContext.ExecuteSqlCommand(sqlBuilder.ToString(), true); sqlBuilder.Clear(); } catch (Exception ex) { logFile.Log($"Ошибка при обновлении пакета предложений: {stats[0] / packageSize}. {ex}"); } } } logFile.Log($"Импорт предложений завершен. Обновлено: {stats[0]}."); }