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

В локальной среде разработки (7.10) создал отдельный пакет, в его зависимости добавил пакет UIv2.

С помощью мастера разделов создал в этом пакете новый раздел. После выгрузки пакета с помощью WorkSpaceConsole и его успешной загрузки в тестовую среду (on-cloud) пытаюсь открыть созданный раздел. В консоли отладчика в браузере получаю такую ошибку:

user: Supervisor/7f3b869f-34f3-4f20-ab4d-7480a5fdf647
file: https://xyz.bpmonline.com/0/configuration/b58905880bd3ab7635160eaf12f09e...
line: 21689
column: 29
message: Uncaught TypeError: Cannot read property 'extendParent' of undefined
date: Thu Jun 01 2017 13:02:22 GMT+0300 (RTZ 2 (зима))
stack: TypeError: Cannot read property 'extendParent' of undefined

Вот как выглядит ошибка в отладчике

Вот как выглядит JS-объект, на котором происходит ошибка из-ха того, что поле schemaStructure undefined

Прежде чем задавать этот вопрос, ознакомился с постом на схожую тему https://community.terrasoft.ru/forum/topic/25523

проверил данные в БД, все необходимые записи в таблицах есть.

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

Заранее благодарен за ответ.

Нравится

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

Андрей,

проверьте всё ли в порядке с наследованием пакетов на той среде, где Вы загрузили новый раздел. Не отличается ли наследование с продуктовой средой :wink:

Алла, проверил, проблем с наследованием пакетов нет. Полагаю, что если такие проблемы были бы, система не сообщила бы об успешной установке пакетов. Ошибка в чем-то другом.

Алла, проверил, проблем с наследованием пакетов нет. Полагаю, что если такие проблемы были бы, система не сообщила бы об успешной установке пакетов. Ошибка в чем-то другом.

Добрый день. Проблема, судя по всему, даже не с наследованием. Попробуйте сгенерировать исходные коды, а также скомпилировать.

После всего вышеописанного внесите изменения в любой пользовательский js файл (вплоть до добавления пробела), а затем сохраните о выполните очистку кэша браузера.

Илья, спасибо за ответ.

Выполнил все точно в указанном порядке. К сожалению не помогло, ошибка прежняя.

Здравствуйте,
Сложно в таком случае подсказать в чем проблема, если это не иерархия и не проблема кеширования. Напишите в поддержку с предоставлением доступа к сайту, что бы они посмотрели в чем там дело.
support@terrasoft.ru

Здравствуйте.
По-моему необходимо перегрузить приложение в IIS
Если есть возможность, проверьте на "чистом" приложении локально, а затем попросите поддержку перезагрузить сайт вручную

Роман, добрый день!

Ошибка воспроизводится на разных серверах, рестарт IIS, перезапуск процесса w3wp не помогают. Пока обошел ошибку тем, что создал вручную новый клиентский модуль - наследника от "Базовая схема раздела (NUI)". С ним ошибок нет. Жду развернутого ответа от поддержки.

из-за старой баги, в системе оставались схемы с одинаковыми заголовками в разных базовых пакетах.
Багу устранили, но последствия могут остаться.
Посмотрите, нет ли у вас в "исходном" приложении нескольких схем с заголовком "Базовая схема раздела" в разных пакетах. Возможно мастер "подхватил" не ту схему.

Показать все комментарии

Добрый день!
Необходимо вызвать планировщик задач из бизнес процесса на запуск другого бизнес процесса в определенное время. В первом бизнес процессе идет обработка объекта с определенным id, есть ли какой либо способ через планировщик передать это id вызванному в указанное время бизнес процессу, для последующей работы с объектом?

Нравится

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

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

Для передачи параметров в процесс, который запускается из планировщика – необходимо использовать словарь.

qrtz_with_param.txt

Здравствуйте, Олег!
Как я поняла, этот метод запустит бизнес процесс сразу после создания джобы. Или там есть какой то анализ параметра starttime в словаре, как даты запуска процесса?

"Родионова Ольга Валентиновна" написал:запустит бизнес процесс сразу после создания джобы

в случае ScheduleImmediateProcessJob, да. всё, что в параметрах - кидается в процесс.

А есть ли какой то способ запустить бизнес процесс в указанное время и при этом передать в него параметр?

В своё время суппорт террасофта кидал мне такое решение

string userName = ....; //- Имя пользователя, от которого запускается бп
var userConnection = ....;
string schedulerJobGroupName = "MyProcessGroup";//- Любое имя группы триггеров
string jobProcessName = "MyBusinessProcess"; //- Название процесса, который нужно запустить
string schedulerJobName = "MyJobName"; //- Любое имя
int startOffset = 100; //- Количество секунд до старта
IDictionary<string, string> parameters = new Dictionary<string, string>();
parameters["Param1"] = ....;
 
var job = AppScheduler.CreateProcessJob(schedulerJobName, schedulerJobGroupName, jobProcessName, userConnection.Workspace.Name, userName, parameters);
var trigger = new SimpleTriggerImpl(schedulerJobName + "Trigger", schedulerJobGroupName, DateTime.UtcNow.AddSeconds(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);

Если вам не подойдёт, посмотрите в VisualStudio параметры создания триггера

new Quartz.Impl.Triggers.SimpleTriggerImpl(...)

Там куча вариантов. И единоразовый, и с повторениями, и который запускается в определённое время и повторяется с определённым интервалом.

Буду пробовать. Большое спасибо!

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

Для установки параметров запуска бизнес-процессов по расписанию через пользовательский интерфейс, мы выпустили соответствующее дополнение к bpm'online. Надеюсь, будет полезным:)

Подробнее здесь https://marketplace.terrasoft.ru/app/extended-business-process-scheduler

Показать все комментарии

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

attributes: {
...
        "SameHandler": {
                dependencies: [
                        {
                                //поле с типом "Дата-время"
                                columns: ["TargetColumn"],
                                methodName: "SameHandlerControl"
                        }
                ]
        },
...

methods: {
...
                "SameHandlerControl": function() {
                        if (window.foo) {
                                window.foo = false;
                        } else {
                                window.foo = true;
                                this.set("TargetColumn", new Date());
                        }
                },

так вот несмотря на то, что при повторном вызове обработчика, выполнение уходит в ветку
...
                        if (window.foo) {
                                window.foo = false;
...

после чего, рекурсивные вызовы, по идее, должны закончиться т.к. значение "TargetColumn" более не меняется, по факту вызовы SameHandlerControl уходят в бесконечную рекурсию

Как этого избежать ?
Почему так происходит ?

PS: классический кейс "самоконтроля поля ввода" - поле реагирует на изменение своего значения вызовом обработчика, который производит проверки и вычисления с введенным значением, по необходимости корректируя/восстанавливая свое собственное значение, предотвращая рекурсивный вызов обработчика.

Нравится

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

Здравствуйте
Интересный случай. Глубоко не копал, но причина вроде бы в последовательности вызова
меняя this.set("TargetColumn", new Date());, вы "дергаете" SameHandlerControl, т.к. атрибут связан с колонкой. И поскольку перед "самовызовом" метода вы меняете флаг выхода, то получается замкнутый цикл

попробуйте вызвать window.foo = true; ПОСЛЕ this.set("TargetColumn", new Date());

мой тестовый код, на котором нет вечного цикла

define("UsrSection1Page", [], function() {
	return {
		entitySchemaName: "UsrSection",
		attributes: {
			"SameHandler": {
				dependencies: [
					{
						columns: ["UsrName"],
						methodName: "SameHandlerControl"
					}
				]
			}
		},
		methods: {
			"SameHandlerControl": function() {
				var n = this.get("UsrName");
				if (window.foo) {
					window.foo = false;
				} else {
					//window.foo = true;
					this.set("UsrName", n + window.foo);
					window.foo = true;
				}
			}
		},
...

Я решил, проблему "отложенным вызовом на 100 мс." смены атрибута который приводит к вызову обработчика в рекурсии

...
setTimeout(function(){
     this.set("TargetColumn", new Date())
}.bind(this), 100);
...

т.е. как только выполнение обработчика завершается корректно - повторный вызов из отложенной функции уже корректно ловит "флаг" и его обрабатывает.

PS:
создается такое впечатление что срабатывание обработчиков - псевдосинхронное, т.е. this.set банально "стакает" текущий контекст, и функция вызывается повторно, не завершившись в предыдущий раз.

Показать все комментарии

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

// скрипт из scr_SalesGridArea

var SalesDataSet = Services.GetNewItemByUSI('ds_Sales');
SalesDataSet.Append(); // после Append SalesDataSet.State=3 (dstInsert)
SalesDataSet('поле') = значение
SalesDataSet.Post();

Как сделать, чтобы после Post() вызывалось function dlDataOnDatasetBeforePost(Dataset, DoPost) // которая написана в wnd_SalesEditScript

в https://www.terrasoft.ru/sdk/index.html?frmname=topic&frmfile=IDatasetEv... написано, что
Если набор данных не находится в состоянии добавления или редактирования записи (значение свойства IDataset::State не равно "dstInsert" или "dstEdit"), то вызывает событие IDatasetEvents::OnDatasetBeforePost.

В какмом же состоянии должен быть набор данных, чтобы вызвать dlDataOnDatasetBeforePost ?

Спасибо.

Нравится

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

Марина,

Post() - это метод датасета, который вызывает событие post, а OnDatasetBeforePost - это обработчик этого события датасета, вызывающийся до того, как будет выполнен post записи.
Соответственно обработчик события OnDatasetBeforePost не может вызываться после вызова метода Post().
Если что-то должно произойти после выполнения метода Post(), то это нужно реализовать в обработчике OnDatasetAfterPost.

Для решения Вашей задачи можно вынести код, который реализован в dlDataOnDatasetBeforePost(Dataset, DoPost) в скрипте wnd_SalesEditScript, в аналогичное событие для сервиса данного датасета.
В таком случае, он будет вызываться всегда при post записи в соответствующую таблицу на уровне приложения, если post будет вызываться на уровне базы данных, то обработчик вызываться не будет.

Показать все комментарии

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

У нас разработан конфигурационный сервис (C#), который считывает из БД Oracle набор записей, создает из них объекты и записывает эти объекты в некий набор таблиц MSSQL (БД CRM Terrasoft).

Запись объектов в таблицы MSSQL производится конструкцией типа new Insert(_userConnection).Into("название таблицы"). К сожалению подобная конструкция подразумевает запись только одного объекта за раз.

Подскажите, пожалуйста, каким образом мы можем переделать данный механизм под пакетную загрузку, чтобы запись в MSSQL таблицу осуществлялась пакетно, то есть например по 100 объектов за раз?

Нравится

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

Если бы данные выбирались из той же базы, можно было бы new InsertSelect, внутри которого бы был запрос на выборку. Но Oracle и MSSQL одновременно...:mrgreen:

В принципе, можно запустить произвольный SQL-запрос при помощи new CustomQuery, а в него и передать текстом запрос на вставку 100 записей.

Показать все комментарии

В бизнес процессе вызываю преднастроенную страницу со своей логикой. Но после ее вызова в БП висит "Выполняется" на преднастроенной страницы. Как сделать чтобы преднастроенная страница считалась "Выполненной" и продолжить выполнение бизнес процесса?

Нравится

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

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

Для того, чтобы элемент [Преднастроенная страница] считался выполненным и процесс перешел к выполнению следующего элемента необходимо – в схеме страницы вызывать метод completeExecution().
Пример можно найти схеме страницы распределения лида - LeadManagementDistributionPageV2

Показать все комментарии

7.10 (Sales)
В типовой карточке Активности (LeadPageV2), поле DetailedResult потребовалось установить его обязательность для заполнения в зависимости от определенных условий и действий пользователя.
в замещающей схеме был добавлен аттрибут

attributes: {
...
    "DetailedResultRequire": {
        type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
        dataValueType: Terrasoft.DataValueType.BOOLEAN,
        value: false
    },
...


соответственно, привязка свойства isRequred для поля расширена через merge

 

diff: {
...
    {
        "operation": "merge",
        "name": "DetailedResult",
        "values": {
            "isRequired": {bindTo: "DetailedResultRequire"}
        }
    },
...


Далее была проработана логика, которая включает в себя реакцию на изменение значения в поле Result для чего были описаны соответствующая зависимость

 

 

attributes: {
...
        "Result": {
            dependencies: [
                {
                    columns: ["Result"],
                    methodName: "DetailedResultRequireController"
                }
            ]
        }
...


ну и собственно сам метод "DetailedResultRequireController",
н/п упростим его до тривиальности -

 

 

methods: {
...
    "DetailedResultRequireController": function() {
        var targetStage = this.get("Status");
        var targetResult = this.get("Result");
        var requireState = false;
        if (targetStage.displayValue === "Завершена" && targetResult.displayValue === "Отменена") {
            requireState = true;
        }
        this.set("DetailedResultRequire", requireState);
    }
...


который производит некие проверки и устанавливать/сбрасывать значение целевого атрибута "DetailedResultRequire", тем самым контролируя обязательность поля "Результат подробно"
PS: Аналогичные кейсы реализовывались множество раз в других типовых карточках и карточках собственной разработки.

 

 

В конечном итоге, поведение весьма удивительное.
Зависимость от изменения значения поля "Результат" => срабатывает.
Метод-обработчик выполняется => устанавливает значение атрибута
=> у искомого поля появляется "*" (звездочка) [т.е. view реагирует на смену значения атрибута]
но это не мешает произвести сохранение карточки, штатные механизмы валидации или игнорируют сей факт или не выполняются вовсе

вот как-то так это выглядит (GIF-ка):

Ума не приложу где можно было бы искать проблему.
Возможно у пользователей сообщества возникали аналогичные ситуации, или есть идеи на счет причин такого поведения ?

Нравится

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

Здравствуйте, попробуйте бизнес правила:
https://academy.terrasoft.ru/documents/technic-sdk/7-8/biznes-pravila-i…

Бизнес-правила, это бизнес-правила, это здесь не при чем. :smile:
Почему может не работать "привязка" обязательности к атрибуту ? - вот вопрос.
Такая логика с точки зрения архитектуры - более чем допустима, до появления бизнес-правил в "перерожденном виде" это использовалось везде и всюду.
Хочется понять природу проблемы.

Почему "звездочка" есть
А валидации - нет ?

"Севостьянов Илья Сергеевич" написал:Почему "звездочка" есть
А валидации - нет ?

Исходя из того, что обсуждается в этой теме http://www.community.terrasoft.ru/forum/topic/12633, такая проблема была обнаружена в более ранних версиях, но, судя по Вашему примеру, так до сих пор и не решена.

Проблема платформы? :wink:

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

В 7.8 и 7.9 активно пользовались биндингами к isRequired, работало нормально, судя по всему в 7.10 наблюдается эта проблема, скорее всего как раз из-за "новых бизнес-правил".
Очень ждем версии с решением, т.к. много кода связано с этими биндингами, да и бизнес-правилами сложную логику не реализовать никак.
Как временное решение - добавлять бизнес правила, которые в зависимости от значения именно атрибута (на который делался биндинг) будет устанавливать обязательность.
Т.е. все ваши биндинги к isRequired необходимо повторить в бизнес-правилах.

Показать все комментарии

Доброго времени суток.

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

Или необходимо скриптом производить insert, а потом update (в тех сущностях где они используются) и delete старых значений?

Нравится

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

Михаил, здравствуйте!

Есть несколько вариантов решения данной проблемы.

1. Вы можете в справочник добавить признак 'IsNotUsed' и реализовать следующую логику в тех сущностях, где значения этого справочника используются: если у записи установлен признак 'IsNotUsed', то в полях новых записей этих сущностей значения не отображать. Конечно, нужно будет записать запрос, который проапдейтит нужные записи справочника и установит признак 'IsNotUsed' в true. Соответственно включить всю эту логику в пакет переноса.
2. Пойти описанным Вами путем - в пакет переноса включить скрипты с инсертом новых записей, апдейтом в сущностях, которые ссылаются на данный справочник, делитом старых значений.

Показать все комментарии

Здравствуйте! Подскажите, пожалуйста, можно ли в местах, отмеченных на скриншоте добавить кнопки "Завершить" и соответствующий процесс?

Нравится

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

Здравствуйте, Мария.
Добавить кнопку "Завершить" в активную строку таблицы (Datagrid) можно.
В элементе Datagrid для этого предусмотрен параметр activeRowActions.
Пример его применения можно посмотреть
https://academy.terrasoft.ru/documents/technic-sdk/7-9/sozdanie-detali-…, там речь про деталь, но в Datagrid как раз добавляются кнопки.
Запуск соответствующего процесса по кнопке можно посмотреть здесь
https://academy.terrasoft.ru/documents/technic-sdk/7-9/zapusk-processa-…
Вот про второй пункт... К сожалению, не сталкивался...

"Maria H" написал: кнопки "Завершить" и соответствующий процесс?

"Лапшин Павел Александрович" написал: К сожалению, не сталкивался...

ПО поводу 2 пункта: Ломаем схему ReminderNotificationsSchema, в diff ищем

{
	"operation": "insert",
	"name": "ActionsButtonPostpone",
	"parentName": "NotificationActivityItemContainer",
	"propertyName": "items",
	"values": {
		"itemType": Terrasoft.ViewItemType.BUTTON,
		"classes": {
			"wrapperClass": ["notificationActionButtonWrap-class"]
		},
		"style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
		"menu": {
			"items": [{
				"caption": {"bindTo": "Resources.Strings.PostponeMenuItemCaption"},
				"menu": {
					"items": {"bindTo": "getNotificationActionButtonMenuItems"},
					"tag": "postpone"
				}
			}, {
				"caption": {"bindTo": "Resources.Strings.CancelMenuItemCaption"},
				"click": {"bindTo": "cancel"}
			}]
		}
	}
}

Накидываем в "menu" свою кнопку и обработчик.

Спасибо за помощь, второй пункт получился :smile:

а в первом случае при использовании activeRowActions возникает ошибка :

Uncaught Terrasoft.InvalidOperationException: Элемент "DataGrid" не должен содержать параментра "activeRowActions"

Подозреваю, что вы пытаетесь сделать merge. Скорее всего так не получится. Попробуйте как в baseSection:

diff:
{
	"operation": "insert",
	"name": "DataGridStopActivityAction",
	"parentName": "DataGrid",
	"propertyName": "activeRowActions",
	"values": {
		"className": "Terrasoft.Button",
		"style": "blue",
		"caption": "Завершить",
		"tag": "stopActivity"
	}
}
 
methods:
onActiveRowAction: function(buttonTag, primaryColumnValue) {
	this.callParent(arguments); //или скопировать switch из baseSection и отредактировать его
	if (buttonTag === "stopActivity") {
		//вызов процесса
	}
}

Спасибо :smile:

Показать все комментарии

Добрый день, столкнулся с такой проблемой после переноса изменение из svn разделы не добавились в список разделов, после изучения бд выяснил что о разделах не было записи в таблицах SysModuleEntity, SysModuleEdit, SysModule после добавления в эти таблицы разделы начали отображаться в списке разделом но при добавлении и их в рабочее место рабочее место не загружается и в консоли появлятся ошибка

user: dgolovachev/e7f5fff2-2fea-4aa6-b704-b306cf31b654
 file: undefined
 line: undefined
 column: undefined
 message: Cannot read property 'imageId' of undefined
 date: Tue May 30 2017 14:42:26 GMT+0600 (Central Asia Standard Time)
 moduleId: ext-window
 moduleName: undefined

подскажите в каком направлении необходимо копать заранее благодарен.

Нравится

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

Дмитрий,

мой совет может показаться Вам банальным: чтобы понять 'в чём корень зла', необходимо выполнить отладку.

Здравствуйте, Дмитрий!

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

Если всеже хотите пойти сложным путем, вот необходимый минимум таблиц, в которых раздел нужно зарегистрировать(тестировали на 7.9.2):

I Этап. Создать запись в таблице SysModuleEntity (таблица, где хранится информация объектах разделов):

SysModuleEntity

insert into SysModuleEntity (SysEntitySchemaUId) values ('AF6DD4AD-1398-4FCE-8837-78DC65AE0F9E')

где [SysEntitySchemaUId] - колонка Uid объекта раздела (например, "UsrRK") в таблице SysSchema;

II Этап. Создать запись в таблице SysModuleEdit (страница редактирования "Page"):

SysModuleEdit

insert into SysModuleEdit (SysModuleEntityId
,UseModuleDetails
,CardSchemaUId
,ActionKindCaption
,ActionKindName
,PageCaption)
values ('8ED522AF-00E1-4595-AC13-643944B005B7'
,1
,'8B22D9BE-4BBC-4B50-80EA-AB6FBB604B7E'
,'Добавить'
,'UsrRK1Page'
,'Card schema: "RK"')

где [SysModuleEntityId] - колонка Id записи таблицы SysModuleEntity из первого этапа (проверка Select Id from SysModuleEntity Where SysEntitySchemaUId='AF6DD4AD-1398-4FCE-8837-78DC65AE0F9E')
[CardSchemaUId] - колонка Uid страницы редактирования объекта (например, "UsrRK1Page") в таблице SysSchema (проверка Select Uid,Name from SysSchema where name like '%UsrRK%'). Нам необходима схема, которая называется "Название объекта + 1Page"
[ActionKindCaption] - Название кнопки в реестре раздела;
[ActionKindName] - Название схемы страницы редактирования;
[PageCaption] - Заголовок схемы страницы редактирования в таблице SysSchema (проверка Select Uid,Name,Caption from SysSchema where name like '%UsrRK1Page%')

III Этап. Создать запись в таблице SysModule (страница раздела "Section"):

SysModule

insert into SysModule (Caption
,SysModuleEntityId
,FolderModeId
,GlobalSearchAvailable
,Code
,SectionModuleSchemaUId
,SectionSchemaUId
,Image32Id) values ('RK'
,'8ED522AF-00E1-4595-AC13-643944B005B7'
,'B659D704-3955-E011-981F-00155D043204'
,1
,'UsrRK'
,'DF58589E-26A6-44D1-B8D4-EDF1734D02B4'
,'B3D153C0-92EF-4A53-B868-9395C3E43516'
,'026742D9-390C-4778-BC46-9FA85C42677A')

где [Caption] - Название раздела (можно брать caption объекта раздела -
[SysModuleEntityId] - колонка Id записи таблицы SysModuleEntity из первого этапа (проверка Select Id from SysModuleEntity Where SysEntitySchemaUId='AF6DD4AD-1398-4FCE-8837-78DC65AE0F9E')
[Code] - Название объекта раздела;
[SectionModuleSchemaUId] - UId модуля SectionModuleV2 с помощью которой открывается схему раздела;
[SectionSchemaUId] - колонка Uid страницы раздела объекта (например, "UsrRK1Section") в таблице SysSchema (проверка Select Uid,Name,Caption from SysSchema where name like '%UsrRK%'). Нам необходима схема, которая называется "Название объекта + 1Section"

Павел, добрый день!

Регистрировал раздел по вашему алгоритму, т.к. мастер у меня упорно не хочет работать. Вроде бы все заработало, но столкнулся с такой проблемой: если создать делать, которая будет ссылаться на нашу новую сущность, то при формировании ссылки на карточку этого раздела ссылка будет некорректной. "Вскрытие" показало, что причина в отсутствии записи в таблице SysModule в колонке CardModuleUId. Без этой записи ссылка формируется без CardModuleV2 и карточка не открывается.

Показать все комментарии