Вопрос

Добрый день ! 

Скажите, можно ли выгрузить все файлы из раздела Документы, которые соответствовали бы определённому формату (excel).  Желательно конечно, отфильтровать документы также по полю "Тип", но это второстепенный вопрос. 

У меня такой же вопрос

1 комментарий
Лучший ответ

Добрый день.

Посмотрите обсуждение подобной темы в этом посте.

Добрый день.

Посмотрите обсуждение подобной темы в этом посте.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день ! 

 

Стоит задача направить на почту контакту письмо с оповещением, что контакт был упомянут в Ленте (в любом объекте). Чаще всего это объект Документ.

Нашла на маркетплейс темплейт, который реализует данную задачу на конфигурации Service. https://marketplace.terrasoft.ru/template/uvedomlenie-ob-upominanii-v-l…  Дабы не изобретать велосипед, хотела переделать бизнес-процесс под нашу конфигурацию, но непонятны некоторые позиции в бизнес процессе. Также установила данный темплейт на триальную версию конфигурацию сервис, и протестила его, но уведомления на почту не падают.

В чем проблема, понять не могу, прошу помощи , чтобы разобраться в данном процессе. Скриншоты настроек элементов бизнес процесса прилагаю.

У меня такой же вопрос

13 комментариев
Лучший ответ

LilyG,

Если не работает отправка уведомлений по оригинальному бизнес-процессу без Ваших правок, то вполне нормально у разработчика процесса уточнить почему. Часто бывают специфические нюансы настроек работы функциональности.

Единственное, я бы проверила корректность настройки почтового ящика - уходят ли хоть какие-то уведомления.

А, если не работает отправка уведомлений после того, как в процесс были внесены изменения с Вашей стороны, тогда без детального анализа внесенных изменений и, возможно, отладки не обойтись.

P.S. Кстати, скриншоты своих изменений Вы так и не прикрепили.

Добрый день.

Все возникшие с настройкой вопросы Вы можете задать разработчику данного бизнес-процесса. Напишите письмо на bpmonlinelabs@bpmonline.com.

Алла Савельева пишет:

Добрый день.

Все возникшие с настройкой вопросы Вы можете задать разработчику данного бизнес-процесса. Напишите письмо на bpmonlinelabs@bpmonline.com.

Добрый день ! 

Разработчику писала изначально, он и рекомендовал поставить темплейт на триальную версию и самостоятельно переделать под свои нужды и конфигурацию.

LilyG,

Если не работает отправка уведомлений по оригинальному бизнес-процессу без Ваших правок, то вполне нормально у разработчика процесса уточнить почему. Часто бывают специфические нюансы настроек работы функциональности.

Единственное, я бы проверила корректность настройки почтового ящика - уходят ли хоть какие-то уведомления.

А, если не работает отправка уведомлений после того, как в процесс были внесены изменения с Вашей стороны, тогда без детального анализа внесенных изменений и, возможно, отладки не обойтись.

P.S. Кстати, скриншоты своих изменений Вы так и не прикрепили.

Алла Савельева,

мне не совсем понятно, для чего используется схема.id у объекта сообщение, можете сказать источники, где я смогу узнать об этом ? Что вообще представляет из себя эта схема ? Гугление ничего не дало по этому вопросу. 

LilyG, причём тут гугление, это же дополнение из маркета, Алла выше привела почту разработчиков.

Судя по этим двум скриншотам, по пустому Id схемы определяется, является ли комментарий в ленте корневым или ответом на другой комментарий и в зависимости от этого отрабатывает различная логика.

Зверев Александр пишет:

LilyG, причём тут гугление, это же дополнение из маркета, Алла выше привела почту разработчиков.

Судя по этим двум скриншотам, по пустому Id схемы определяется, является ли комментарий в ленте корневым или ответом на другой комментарий и в зависимости от этого отрабатывает различная логика.

Разработчики отправили меня переделывать процесс самостоятельно, я писала выше. А чтобы его переделать, нужно понимать что происходит при выполнении процесса. А чтобы это понимать, я должна знать ту часть формул,что не описаны в разделе "Формулы" на академии, например, упоминание схем. 

Спасибо. 

Это обычное значение справочного поля, которое может быть пустым или заполненным.

Зверев Александр,

Александр, могли бы Вы подсказать, как человек, который разбирается в формулах, почему стоит именно такая формула проверки перед отправкой еmail ? 

[#Читать пользователя контакта.Первый элемент результирующей коллекции.Тип подключения#]==0&&[#Message Schema ID#]==[#Cases Schema ID#]&&[#Читать системную настройку NoReplyNotificationMailboxSettings.Первый элемент результирующей коллекции.Значение уникального идентификатора#]!=Guid.Empty&&[#Читать контакта.Первый элемент результирующей коллекции.Email#]!=String.Empty

Тип  подключения пользователя: что это ? я нашла данную колонку в пользователях, вывела её и у всех стоит "0". Но что означает этот ноль непонятно .

Системная настройка не должна быть пустой (это выглядит логично, но я не нашла данную системную настройку "NoReplyNotificationMailboxSettings" в нашей конфигурации и в гугле).

Не пустой email тоже выглядит логично.

И главный вопрос, зачем приравнивать id Схем сообщения и кейса ? 

Лилия, вопросы, почему в процессе написали именно такое условие, лучше адресовать его авторам. Если Вам не нужно какое-то условие, можете его убрать, но процесс после этого может работать уже не так, как задумано при его создании.

По типу пользователя, см. тему.

Системной настройки с таким кодом стандартно не вижу, возможно, она идёт в пакете с этим БП. Судя по названию, в ней может хранится Id записи о ящике «noreply@...».

Процесс предназначен для работы с напоминаниями раздела обращений, потому и сравнивается Id со схемой Case.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Доброго времени суток!Возникла необходимость учитывать регистр строки в фильтре при запросе esq С# . Никто не встречался с такой проблемой?Как это можно реализовать?

У меня такой же вопрос

3 комментария

Система полагается на стандартные настройки базы данных. В MS SQL по умолчанию регистр не учитывается, настройка меняется на уровне всей базы, как описано тут. Только учтите, что работу системы с изменёнными настройками регистрозависимости никто не тестировал и сайт может заработать некорректно в других местах.

Зверев Александр,

Благодарю за ответ

Может кому пригодится. Решили эту проблему следующим образом - конвертировали строку в base64.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день! Прошу подсказать, как в печатных формах менять окончания, к примеру ОБЩАЯ СУММА: 46 232 778,78 "Рублей", Цена за ед. в "Рублях", когда Валюта = Рубль без привлечения разработчика 

 

 

 

У меня такой же вопрос

2 комментария

Можно с помощью простой функции "Заменить" (Ctrl+H)

Не знаю, какой именно Вы используете из механизмов отчётов, но подозреваю, что без разработки не получится. Если в движке отчётов есть возможность написать логику макроса для подстановки, можно функцией по числовому значению получать нужный текст. Вот пример функции на JS, под C# адаптировать будет несложно.

А если отчёт не позволяет вычислений, можно в объекте рядом с числовым полем добавить текстовое, которое заполнять аналогичным образом в бизнес-процессе на создании и изменении записи, а затем подставить его значение в отчёт.

Также см. статью о том, какие макросы для Word-отчётов в системе есть стандартно, а вот статья о создании своего макроса.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Коллеги, добрый день.

Столкнулся с проблемой отображения уведомлений в коммуникационной панели.

Задача: при добавлении нового участника в деталь "команда" в карточке продажи - уведомлять добавленного участника в коммуникационной панели.

Делал через бп (скриншот во вложении).

При смене NotificationType на Notification - во вкладке системных уведомлений все отображается корректно. Можно перейти в продажу по ссылке.
При значении Reminding - во вкладке напоминаний пустота (а напоминание нужно как раз именно там). При этом на счетчике самой вкладки видно, что напоминание есть.

Решаема ли задача через бп? Или все же нужно кодить? Сначала подумал что нужно создавать провайдер, но я так понял что после 7.12 схема поменялась? Вообщем буду рад подсказке как это корректнее всего сделать.

С Активностями-Участниками аналогичный бп работает нормально (уведомления в напоминаниях отображаются).

Прикрепленные файлы
111111.png876.06 КБ

У меня такой же вопрос

5 комментариев

Возможно, при создании записи в таблице Reminding не заполнены нужными значениями все поля. Сравните в базе значения у той записи, что отображается у пользователя в этом разделе верно и у Вашей, созданной при помощи БП.

Зверев Александр,

Александр, спасибо за подсказку. В таблице Reminding поле SourceId получает null. Не совсем пока понятно что с этим сделать, но это уже хоть что-то) Буду разбираться.

Александр, на Вашем скриншоте в элементе БП создания напоминания нет заполнения этого поля SourceId, нужно добавить. Возможные варианты значений есть в таблице справочника RemindingSource.

Зверев Александр,

Александр, так я тоже пробовал еще в самом начале. К сожалению никакого эффекта это не дает (но кстати SourceId в таблице заполняется, это да).

На данный момент оставил уведомления как NotificationType = Notification. Но хотелось бы конечно разобраться.

Сравните значения полей с уже существующими записями,которые отобразились верно.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день, коллеги! 

Есть задача: сделать веб-сервис, принимающий на вход сложное json-тело.

В ходе реализации столкнулась с двумя проблемами:

1. Не нашла, как описать прием сложного параметра в сервисе, кроме робкого указания на модификаторы [DataContract] и [DataMember]. Подскажите, где-нибудь есть информация об этом? 

2. При вызове из Postman сервис возвращает ответ "403 - Вы не имеете разрешения на просмотр этого каталога пли страницы." (скриншот ниже). Нужно ли где-то отдельно прописывать права на доступ к сервисам?

 

Скриншот ошибки:

Листинг пример json тела запроса.

{
"scoring_events" : [
		{
			"type" : "pageview",
			"page_url" : "https://bpmonline.com/",
			"datetime_utc" : "2018-08-08 12:00:12",
			"responsible_user" : {
				"name" : "Иван Иванов",
				"email" : "i.ivanov@yandex.ru",
				"type" : "user"
			},
			"partner" : {
				"name" : "ООО Ромашка"
				"bpm_id" : "783967ef-c629-4f1d-8cd4-3b3dba955ffc",
				"contact_email" : "n.ivanova@yandex.ru"
			}
		},
		...
		{
			...
		}
	]
}

 

листинг сервиса:

namespace Terrasoft.Configuration.WScoringService
{
	using System;
<...>
#region Class: WScoringService 
	[ServiceContract]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
	public class WScoringService : BaseService
	{
        private WScoringServiceResponse wScoringServiceResponse;

        #region Methods: Public
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
        ResponseFormat = WebMessageFormat.Json)]
        public string AddScoringEvent(List<ScoringEvent> scoring_events)
        {
            if (scoring_events.IsEmpty()) wScoringServiceResponse = new WScoringServiceResponse(true, "empty");
            else wScoringServiceResponse = new WScoringServiceResponse(true, scoring_events[0].ToString());
            return wScoringServiceResponse.ToJsonString();
        }
        #endregion
        #region  DataContract
	    [DataContract]
	    public class ScoringEvent
	    {
	    	[DataMember]
	        public string type;
	        [DataMember]
	        public string page_url;
	        [DataMember]
	        public string datetime_utc;
	        [DataMember]
	        public ResponsibleUser responsible_user;
	        [DataMember]
	        public Partner partner;
	        public override string ToString()
	        {
	            string result;
	            result = "type=" + type + ";";
	            result += "page_url=" + page_url + ";";
	            result += "datetime_utc=" + datetime_utc + ";";
	            result += "responsible_user_name=" + responsible_user.name + ";";
	            result += "partner_name=" + partner.name + ";\n";
	            return result;
	        }
	    }
	    [DataContract]
	    public struct ResponsibleUser
	    {
	    	[DataMember]
	        public string name;
	        [DataMember]
	        public string email;
	        [DataMember]
	        public string type;
	    }
	    [DataContract]
	    public struct Partner
	    {
	    	[DataMember]
	        public string name;
	        [DataMember]
	        public string bpm_id;
	        [DataMember]
	        public string contact_email;
	    }
	    #endregion
    }
    #endregion

    #region Class: WScoringServiceResponse
    public class WScoringServiceResponse
    {
        private bool success;
        private string message;
        public WScoringServiceResponse() { }
        public WScoringServiceResponse(bool success, string message = null)
        {
            this.success = success;
            this.message = message;
        }
        public string ToJsonString()
        {
            string result = "{\"status\":\"";
            if (success) result += "ok\",";
            else result += "error\",";
            result += "\"message\":\"" + message+ "\"}";
            return result;
        }
    }
    #endregion
}

 

У меня такой же вопрос

1 комментарий

Примеры сервисов можно найти в конфигурации. Например, [DataContract] и [DataMember] применяют в CurrentUserService так:

[DataContract]
public class UserCultureInfo
{
	[DataMember(Name = "timeZoneCode")]
	public string TimeZoneCode { get; set; }
 
	[DataMember(Name = "timeZoneName")]
	public string TimeZoneName { get; set; }
 
	[DataMember(Name = "timeZoneId")]
	public Guid TimeZoneId { get; set; }
 
	[DataMember(Name = "cultureId")]
	public Guid CultureId { get; set; }
 
	[DataMember(Name = "cultureName")]
	public string CultureName { get; set; }
 
	[DataMember(Name = "cultureLanguage")]
	public string CultureLanguage { get; set; }
 
	[DataMember(Name = "dateTimeFormatId")]
	public Guid DateTimeFormatId { get; set; }
 
	[DataMember(Name = "dateTimeFormatName")]
	public string DateTimeFormatName { get; set; }
}

По поводу 403, такое бывает, если при отправке запроса к сервису не передать CSRF-токен.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Коллеги, приветствую!

Столкнулся с проблемой у детали с редактируемым реестром.

Не получается заставить работать кнопку "настроить деталь" в карточке. Пишет что деталь не зарегистрирована в справочнике деталей.

Делаю все по инструкции из https://academy.terrasoft.ru/documents/technic-sdk/7-14/detal-s-redaktiruemym-reestrom (включая регистрацию через sql-запрос)

+ пункт 3 из https://academy.terrasoft.ru/documents/technic-sdk/7-14/detal-so-stranicey-dobavleniya (включая регистрацию связи между схемой объекта детали и схемой страницы редактирования записи детали через sql-запрос и перекомпиляцию в конфигурации)

Так же пробовал на демо-стенде с грубо говоря копипастом из инструкции - результат тот же.

Что забыл\упустил? Заранее благодарю!

 

У меня такой же вопрос

2 комментария
Лучший ответ

Здравствуйте.

Проверьте, действительно, ли добавилась нужная информация в SysDetails, SysModuleEntity и SysModuleEdit в базе данных Вашего сайта.

Это можно сделать с помощью sql-запроса к базе данных.

P.S. Обычно, чтобы не возиться с написанием специальных sql-запросов для регистрации детали, я сначала создаю стандартную деталь через мастер деталей, а потом вношу изменения в схему самой детали, чтобы она стала редактируемой.

Здравствуйте.

Проверьте, действительно, ли добавилась нужная информация в SysDetails, SysModuleEntity и SysModuleEdit в базе данных Вашего сайта.

Это можно сделать с помощью sql-запроса к базе данных.

P.S. Обычно, чтобы не возиться с написанием специальных sql-запросов для регистрации детали, я сначала создаю стандартную деталь через мастер деталей, а потом вношу изменения в схему самой детали, чтобы она стала редактируемой.

Алла Савельева,

Алла, добрый день!
По базе вроде бы все на своих местах. Но так или иначе ваш способ сработал, спасибо вам огромное)
Надо будет сравнить таблицы и разобраться с вариантом "вручную".

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Всем доброго времени суток! 

Столкнулся со следующей проблемой, у нас в системе были кастомные Excel отчеты, выгружались посредствам библиотеки ClosedXml, и все работало, но с версии 7.14 перестало работать. Высыпаются ошибки в зависимостях:

Terrasoft.Web.Common.ServiceModel.ErrorHandler ProvideFault - Метод не найден: "System.IO.Packaging.PackageProperties DocumentFormat.OpenXml.Packaging.OpenXmlPackage.get_PackageProperties()".
System.MissingMethodException: Метод не найден: "System.IO.Packaging.PackageProperties DocumentFormat.OpenXml.Packaging.OpenXmlPackage.get_PackageProperties()

Пробовал устанавливать разные версии библиотеки не помогло.

Кто работал с библиотекой ClosedXml в bpm'online, может знает какую версию использовать?

Текущая версия crm 7.14.4 

заранее благодарен.

У меня такой же вопрос

4 комментария
Лучший ответ

Столкнулся, к сожалению. пришлось все переписывать... В ClosedXML используются библиотеки DocumentFormat.OpenXml, в версии 7.14 видимо обновили версию библиотеки/зависимых библиотек и все. Мучался часа 3 с зависимостями, потом плюнул и переписал на OpenXml генерацию xls

Столкнулся, к сожалению. пришлось все переписывать... В ClosedXML используются библиотеки DocumentFormat.OpenXml, в версии 7.14 видимо обновили версию библиотеки/зависимых библиотек и все. Мучался часа 3 с зависимостями, потом плюнул и переписал на OpenXml генерацию xls

А что говорит по этому вопросу служба поддержки? Что они рекомендуют?

Алла Савельева,

Здравствуйте! Пока ничего. Анализирует предоставленный мною лог.

Нигрескул Алексей,

Поделитесь потом здесь ответом, очень интересует данная тема. Спасибо)

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день!

Возможно ли сделать поле Мобильный телефон стандартным условием поиска Контакта (при выборе из справочника) в одном разделе.

У меня такой же вопрос

4 комментария

Доброе утро!

Смотрите обсуждения в этом посте и в этом.

Ещё можно попробовать добавить в карточку выбора из справочника отдельное поле, как обсуждают здесь.

Забыл упомянуть, справочник не обычный а multilookup (Выбор из контактов и аккаунтов).

Решил пойти сложным путем, добавил схему CustomLookupPage (расширил MultiLookupModule) и в нем переопределил 

onTabChanged и 
generateViewModel

 для поиска по мобильному телефону у контакта. Код: 

define("CustomLookupPage", ["LookupPage", "LookupPageViewGenerator", "LookupPageViewModelGenerator", "LookupUtilities", "css!LookupPageCSS"],
   function(LookupPage, LookupPageViewGenerator, LookupPageViewModelGenerator) {

      return Ext.define("Terrasoft.configuration.CustomLookupPage", {
         alternateClassName: "Terrasoft.CustomLookupPage",
         extend: "Terrasoft.MultiLookupModule",

         gridWrapClasses: ["multi-lookup-control"],


         onTabChanged: function(activeTab) {
            var lookupsInfo = this.get("LookupsInfo");
            Terrasoft.each(lookupsInfo, function(lookupInfo) {
               if (activeTab.get("Name") !== lookupInfo.entitySchemaName) {
                  return true;
               }
               this.lookupInfo = lookupInfo;

               this.getSchemaAndProfile(lookupInfo.lookupPostfix, function(entitySchema, profile) {
                  this.isClearGridData = true;
                  this.set("gridProfile", profile);
                  this.entitySchema = entitySchema;
                  this.initLoadedColumns();
                  var searchColumn = this.get("searchColumn");
                  if (!entitySchema.columns[searchColumn.value]) {
                     this.set("searchColumn", {
                        value: this.entitySchema.primaryDisplayColumn.name,
                        displayValue: this.entitySchema.primaryDisplayColumn.caption
                     });
                     this.set("searchData", "");
                  }
                  this.set("LookupInfo", this.lookupInfo);
                  this.load(profile, function() {
                     var lookupInfo = this.lookupInfo;
                     var entitySchema = this.entitySchema;

                     //у контакта поиск по мобильному телефону
                     if (this.entitySchema.name == "Contact") {
                        this.set("searchColumn", {
                           value: "MobilePhone",
                           displayValue: "Мобильный телефон"
                        });
                     } else {
                        this.set("searchColumn", {
                           value: entitySchema.primaryDisplayColumn.name,
                           displayValue: entitySchema.primaryDisplayColumn.caption
                        });
                     }

                     var captionLookup = this.getLookupCaption(entitySchema, lookupInfo);
                     this.set("captionLookup", captionLookup);
                     this.set("lookupSchemaName", entitySchema.name);
                     this.setSearchEditFocused();
                  }.bind(this));
               });
            }, this);
         },

         generateViewModel: function() {

            var viewModelConfig = LookupPageViewModelGenerator.generate(this.lookupInfo);

            //у контакта поиск по мобильному телефону
            viewModelConfig.values.searchColumn = {
               value: "MobilePhone",
               displayValue: "Мобильный телефон"
            };

            if (!this.lookupInfo.columnValue && this.lookupInfo.searchValue) {
               viewModelConfig.values.searchData = this.lookupInfo.searchValue;
               viewModelConfig.values.previousSearchData = this.lookupInfo.searchValue;
            }
            var viewModel = this.Ext.create("Terrasoft.BaseViewModel", viewModelConfig);
            viewModel.Ext = this.Ext;
            viewModel.sandbox = this.sandbox;
            viewModel.Terrasoft = this.Terrasoft;
            if (this.lookupInfo.updateViewModel) {
               this.lookupInfo.updateViewModel.call(viewModel);
            }
            viewModel.initCaptionLookup();
            viewModel.initHasActions();
            viewModel.initLoadedColumns();
            if (!this.Ext.isEmpty(this.lookupInfo.filterObjectPath)) {
               viewModel.updateFilterByFilterObjectPath(this.lookupInfo.filters, this.lookupInfo.filterObjectPath);
            }
            if (this.lookupInfo.hideActions) {
               viewModel.set("hasActions", false);
            }
            return viewModel;
         },
      });
   });

Отображается поле на странице следующим образом:

"SxShipper": {
   "caption": { "bindTo": "Resources.Strings.SxShipper" },
   "dataValueType": this.Terrasoft.DataValueType.LOOKUP,
   //"multiLookupColumns": ["SxShipperContact", "SxShipperAccount"],
   "lookupListConfig": function() {
      return this.getLookupListConfig();
   },
   "isRequired": true
},

...

getLookupListConfig: function() {
   var multiLookupColumns = ["Contact", "Account"];
   var multiLookupConfig = multiLookupColumns.map(function(column) {
      return {
         entitySchemaName: column,
         columnName: "SxShipper",
         multiLookupColumnName: "SxShipper" + column,
         multiSelect: false,
         hideActions: true
      };
   }, this);
   var config = {
      lookupModuleId: this.Terrasoft.generateGUID(),
      lookupPageName: "CustomLookupPage",
      multiLookupConfig: multiLookupConfig
   };

   return config;
},

Поиск по телефону рабоает хорошо, но в поле не подтягивается значение, и при выборе из справочника в поле тоже ничего не проставляется

В чем может быть дело и в каком направлении копать?

Попробуйте для начала добиться нормальной работы лукапа по обычному ФИО, а затем модифицируйте под поиск по телефону.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Всем доброго времени суток! Столкнулся со следующей проблемой. Есть БП который запускается после изменения записи, в нем есть скрипт-таск в котором определяется заголовок Origin - System.Web.HttpContext.Current.Request.Headers["Origin"], если изменение производились через карточку записи то заголовок присутствовал и процесс шел по одной ветке, если же изменение произошло кодом через интеграцию, то заголовок был пустой. Это работало до недавнего времени, сейчас же System.Web.HttpContext.Current == null.

Кто нибудь с таким сталкивался?

У меня такой же вопрос

2 комментария

Разобрался, в настройке начального сигнала стояло выполнять след. эл-ты в фоне. Из-за этого не читалось.

Лучше вообще не завязываться на такие недокументированные возможности, а сразу сделать зримое различие в данных, приходящих из интерфейса или по интеграции. Например, добавить в объект дополнительное поле, логическое или справочник и при работе интеграции его заполнять. Или просто запускать интеграцию под отдельным пользователем и смотреть значение ModifiedById.

Войдите или зарегистрируйтесь, чтобы комментировать