Столкнулся со следующей проблемой в BPMOnline ServiceDesk 5.4:
- Необходимо в Аналитике сделать ПОЧАСОВОЙ график регистрации инцидентов.

Но при настройке графика для поля "Дата/время" предлагается только форматы "Год, Месяц, Неделя, День". Соответственно вопрос каким образом добавить формат "Час"??

Нравится

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

Решил проблему сам путем добавления в объект SysDateTimeFormat следующей строчки:

insert into SysDateTimeFormat(Name,Code) values('Час','Hour')

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

Добрый день,

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

Как ее активизировать?

Нравится

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

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

На сколько я понимаю, то речь идет об "SmartCloud Connect for bpm’online".

Более детально Вы можете ознакомиться по ссылке: https://marketplace.terrasoft.ru/app/67

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

При попытке редактирования записей созданной мной детали, сразу возникает разрушительный сбой

Кнопки *Добавить* и *Удалить* отрабатывают без проблем.
Проверка MessageBox(Dataset.State); в обработчике выдает почему-то: 1.
На других, нормально работающих в режиме изменения записи, деталях такая-же проверка выдает 2 , т.е. dstEdit. Где могло произойти нарушение логики?

Нравится

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

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

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

Алла, добрый день!
В какую часть кода установить debugger ? Видимо туда, где сразу начинается выполняться код после нажатия *Изменить* ? В администраторе видно что на кнопку btnEdit обработчик btnEditOnClick выставлен, но он не обрабатывается в wnd_MyDetailGridAreaScript. A где тогда?

Ну а в обработчик кнопки *Оk* карточки редактирования датасет уже в неправильном состоянии приходит:
function btnOKOnClick(Control) {
var Dataset = dlData.Dataset ;
MessageBox(Dataset.State); // Здесь на экран выводится 1

Что означает Dataset.State == 1 ?

Алла, добрый день!
В какую часть кода установить debugger ? Видимо туда, где сразу начинается выполняться код после нажатия *Изменить* ? В администраторе видно что на кнопку btnEdit обработчик btnEditOnClick выставлен, но он не обрабатывается в wnd_MyDetailGridAreaScript. A где тогда?

Ну а в обработчик кнопки *Оk* карточки редактирования датасет уже в неправильном состоянии приходит:
function btnOKOnClick(Control) {
var Dataset = dlData.Dataset ;
MessageBox(Dataset.State); // Здесь на экран выводится 1

Что означает Dataset.State == 1 ?

Алла, добрый день!
В какую часть кода установить debugger ? Видимо туда, где сразу начинается выполняться код после нажатия *Изменить* ? В администраторе видно что на кнопку btnEdit обработчик btnEditOnClick выставлен, но он не обрабатывается в wnd_MyDetailGridAreaScript. A где тогда?

Ну а в обработчик кнопки *Оk* карточки редактирования датасет уже в неправильном состоянии приходит:
function btnOKOnClick(Control) {
var Dataset = dlData.Dataset ;
MessageBox(Dataset.State); // Здесь на экран выводится 1

Что означает Dataset.State == 1 ?

Установите debugger на обработчик OnPrepare карточки редактирования и посмотрите, в каком состоянии находится датасет.

Если для карточки редактирования обработчик OnPrepare не переопределен, тогда установите debugger в обработчик OnPrepare родительской карточки редактирования (она указана в свойстве TemplateWindowUSI самого окна карточки редактирования).

"Кудинов Дмитрий Станиславович" написал:В администраторе видно что на кнопку btnEdit обработчик btnEditOnClick выставлен, но он не обрабатывается в wnd_MyDetailGridAreaScript. A где тогда?

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

"Кудинов Дмитрий Станиславович" написал:Что означает Dataset.State == 1 ?

Это означает, что датасет находится в состоянии просмотра.
Для того, чтобы добавить данные в датасет, он должен находится в состоянии 2 (редактирования) или 3 (вставки).

Алла, не подскажете как от этого назойливого окна избавится ?

Каждый раз спрашивает при запуске VS, хотя галочка *Использовать ... по умолчанию* выставлена.

В справке написано:

Запуск JIT-отладки в случае возникновения ошибки
В диалоговом окне "JIT-отладка" в списке Доступные отладчики выберите пункт Новый экземпляр Visual Studio 2015 или выберите уже работающий экземпляр Visual Studio.
Чтобы автоматически использовать Visual Studio для всех будущих сбоев, выберите команду Использовать выбранный отладчик по умолчанию.
Если нужно выбрать типы кода для отладки, нажмите кнопку Выбрать отладчики вручную. Если этого не сделать, Visual Studio автоматически выбирает отладчики, подходящие для типа кода в приложении.
Нажмите кнопку ОК.

Если Visual Studio работает не так, стоит обратиться в службу поддержки Microsoft.
Также см. обсуждение похожего вопроса тут.

Все происходит в scr_BaseDBEditUtils между этими двумя функциями(см.ниже):

function OpenDatasetWithRecordID(Dataset, ID) { // здесь еще 0
Dataset.Close();
ApplyDatasetIDFilter(Dataset, ID, true);
Dataset.Open(); // здесь еще 0

А здесь уже 1 на входе:

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

Дмитрий,

в таком случае Вам нужно проверить, что происходит в обработчиках OnDatasetBeforeOpen и OnDatasetAfterOpen у датасета детали.

A можно самому переопределить с 1 на 2 ?
Если :
Dataset.State = 2;
тогда ошибка .

"Савельева Алла" написал: OnDatasetBeforeOpen и OnDatasetAfterOpen у датасета детали.

А куда debugger втыкать? Обработчики у датасета явно не определены.

Не нужно. Изменение состояния Dataset-а происходит автоматически при выполнении его методов.

"Зверев Александр" написал:Не нужно.

Уточните что делать не нужно. Не нужно проверять, что происходит в обработчиках OnDatasetBeforeOpen и OnDatasetAfterOpen или не нужно самому переопределять с 1 на 2 ?

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

В датасете не были проставлены галочки *Генерировать запрос на обновление* , *Редактирование*.
Александр, спасибо что обратили мое внимание на датасет!

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

function edtContactIDOnPrepareSelectWindow(LookupDataControl, SelectWindow) {

var AccountID = Self.Attributes('ParentItemID');
if (AccountID){
var LookupDataset = LookupDataControl.DataField.LookupDataset;
ApplyDatasetFilter(LookupDataset, 'AccountID', AccountID, true); //фильтруем контактов по текущему контрагенту-родителю
LookupDataset.Attributes('DontFilter') = true;
debugger;
}
}


1.Что делает строка: LookupDataset.Attributes('DontFilter') = true; ? Для чего это?
2. Где в дебаггере VS можно посмотреть эти .Attributes ? Допустим, мне налету нужно проанализировать значение: Self.Attributes('ParentItemID')

Это какая-то доработка, в коробке «DontFilter» нигде не упоминается.
В отладчике для этой цели есть окно «Watch».

Получается что в Watch значение поля 'ParentItemID' у Self.Attributes нет ? Где значения всех этих атрибутов?

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

Обычно значение аттрибута 'ParentItemID' присваивается при инициализации детали.

Для примера посмотрите как инициализируются детали раздела [Контрагенты].

Инциализация происходит в окне раздела в функции RefreshDetails().

Если мы говорим о разделе [Контрагенты], то в качестве значения атрибута 'ParentItemID' присваивается ID текущей записи контрагента.

"Кудинов Дмитрий Станиславович" написал:Где значения всех этих атрибутов?

Вам нужно самостоятельно в строке окна Watch прописать строчку Self.Attributes('ParentItemID').

Допустим на датасет наложили фильтр:

ApplyDatasetFilter(CampaignDataset, 'CampaignID', CampaignID , true); // apply filter

Можно ли Watch увидеть какое число записей осталось в CampaignDataset после наложения фильтра?
Где это свойство подсмотреть?

Dataset.RecordsCount

Как в цикле получить доступ к каждой записи датасета, чтобы взять значение какого-либо поля?

Например, таким образом:

Dataset.Open();
while (!Dataset.IsEOF) {
var AccountID = Dataset('AccountID');
Dataset.GotoNext();
}
Dataset.Close();

Где можно отключить вывод *названия воздействия* в верхней части карточки редактирования воздействия?

В скрипте scr_BaseDBEditUtils есть функция SetEditWindowCaption, которая его заполняет. Нужно внести доработки, чтобы она в нужном случае ничего не делала. К примеру, в скрипте карточки воздействия на OnPrepare присваивать окну какой-то атрибут, а в этой функции его проверять.

Каким образом можно отключить подчеркивание текста в dgdtLookup колонках. Т.е. чтобы текст оставался Lookup, но без подчеркивания.

Дмитрий,

по этому вопросу открыт другой топик - вот ссылка на него:
http://www.community.terrasoft.ru/forum/topic/25026

"Савельева Алла" написал:по этому вопросу открыт другой топик - вот ссылка на него:
http://www.community.terrasoft.ru/forum/topic/25026


Это я создал новую тему, т.к. Александр справедливо заметил, что данный вопрос к текущей теме не имеет отношения.

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

Здравствуйте, сложилась такая ситуация: есть пользовательский пакет, в котором находятся детали, объекты, схемы для пользовательского раздела, необходимо перенести пользовательский пакет с одного сайта на другой.
Пакет я перенёс, установив его из SVN, а вот раздел сам не добавился. В связи с этим, возник вопрос, как мне добавить раздел? Есть ли вообще такая возможность? Сталкивался ли кто-нибудь с такой "проблемой". Заранее спасибо за ответ.

Нравится

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

Добрый день.

Попробуйте настроить рабочее место.

"Адаменко Александр Викторович" написал:

Добрый день.

Попробуйте настроить рабочее место.


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

Попробуйте найти свой раздел в SysModule в базе (проверить есть ли он вообще в системе). Если нет, то как вариант можно через sql добавить его.

Здравствуйте, Антон.

После установки пакета из SVN необходимо выполнить следующие действия:

1. Сгенерировать для требующих генерации.
2. Компилировать все.
3. Выбрать элементы, структура которых менялась. Обновить для них структуру БД.
4. На вкладке Данные отобразить колонки Текст последней ошибки и Требует установки в БД. Установить выбранные элементы.
5. На вкладке SQL сценарии Установить выбранные элементы.

Более подробную информацию вы можете найти по следующей ссылке:

https://www.youtube.com/watch?v=DKVo4I5uTXA&feature=youtu.be (с 03:55:00).

"Мария Ватулина" написал:

Здравствуйте, Антон.

После установки пакета из SVN необходимо выполнить следующие действия:

1. Сгенерировать для требующих генерации.

2. Компилировать все.

3. Выбрать элементы, структура которых менялась. Обновить для них структуру БД.

4. На вкладке Данные отобразить колонки Текст последней ошибки и Требует установки в БД. Установить выбранные элементы.

5. На вкладке SQL сценарии Установить выбранные элементы.

Более подробную информацию вы можете найти по следующей ссылке:

https://www.youtube.com/watch?v=DKVo4I5uTXA&feature=youtu.be (с 03:55:00).

Спасибо большое, помогло

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

Добрый день.
Развернул on-site BPMOnline 7.9.0.1228. Настроил Https.
Сайт работает нормально, но смущает в ошибка в консоли:

Uncaught ReferenceError: calq is not defined.

Подскажите, пожалуйста, что за ошибка и как её побороть?

Нравится

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

Здравствуйте, Игорь!

По сути данная ошибка не влияет на работоспособность системы, но, если в этом есть необходимость, то для решения необходимо очистить значение системной настройки с кодом "GoogleTagManagerScript".

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

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

Есть коробочная установка sales 7.8 и коробочный AsteriskNOW (под управлением FreePBX), на Asterisk'е настроено два внутренних номера 101 и 102 (оба в контексте from-internal) с созданием соответствующих пользователей. Протокол PJSIP. Звонки с софтфонов между этими номерами нормально проходят.

Установлен и настроен коннектор BPM - Asterisk, в консоли выдаётся сообщение об успешном подключении к серверу в профиле отображается статус Активен. Но при попытке совершения вызова из bpm выдаётся ошибка:
[Telephony] {"connectionUId":"701d02fe-d0a9-4b81-8a97-c00afb97b22c","eventType":0,"content":"{"errorType":0,"data":"Asterisk error: OriginateResponse: Failure, Target Number = 102"}","contentType":"MsgErrorInfo"} 1 all-combined.js:1813:491

В консоли Астериска при этом появляется:
WARNING[7801]: chan_sip.c:6084 create_addr: Purely numeric hostname (101), and not a peer--rejecting!

Т.е. Астериск отклоняет осуществление вызова с прописанного в bpm номера (101).

В связи с этим вопрос: подскажите, пожалуйста, кто сталкивался - какие дополнительные настройки нужны в коробочной Asterisk/FreePBX для запуска интеграции?

Нравится

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

Александр, добрый день.

Исходя из приведенных данных можно предположить, что Originate выполняется на peer "SIP/102" (исходя из того, что предупреждение от модуля chan_sip). Вы же ранее указали, что используете модуль PJSIP. Наиболее вероятно, что проблема в этом. Больше точно можно было бы сказать из полного запроса Orginate и полного ответа. Посмотреть полную информацию можно в файлах логов интеграционной службы TMS. Если предположение верное, обратитесь, пожалуйста, в поддержку для получения интеграционной службы, которая работает с PJSIP модулем.

Да, дело было в модуле pjsip. Поменял его в Asterisk на sip, ошибка ушла.
Спасибо.

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

Есть кнопка в разделе активности, нужно при ее нажатии открыть мини карточку контакта(добавление новой записи), подскажите как это сделать

Нравится

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

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

Вы можете добавить обработчик события нажатия кнопки.

Рекомендую посмотреть реализацию метода addRecord() в схеме BaseProfileSchema (не уверен, что в 7.8.0 есть - в 7.9.0 точно есть).

нашел вот такое:
var entitySchemaName = this.getEntitySchemaName(typeColumnValue);
this.openAddMiniPage({
entitySchemaName: entitySchemaName,
moduleId: this.getMiniPageSandboxId(entitySchemaName),
valuePairs: this.getOpenDefaultValues(typeColumnValue, ConfigurationEnums.CardStateV2.ADD)
});
если мне нужно мини карточку контакта то нужно подставить другой entitySchemaName, но что такое typeColumnValue и ConfigurationEnums.CardStateV2?

Виталий, насколько я понял, то:

- typeColumnValue — значение колонки типизации записи (https://academy.terrasoft.ru/sites/default/files/documents/docs/technic…)

- ConfigurationEnums.CardStateV2 - текущее состояния страницы. В данном случае указывается, что действиебудет доступно для редактирования только в режиме добавления записи, а в режиме изменения/копирования будет неактивно (схема ConfigurationEnums).

при чем тут typeColumnValue??? и
entitySchemaName в ContactMiniPage указан Contact
разве нужно брать не ИД - "ViewModule_MiniPageListener_MiniPage_ContactMiniPage"?

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

typeColumnValue - значение по которому типизируется раздел (в одном разделе может быть несколько страниц редактирования в зависимости от значения поля, по которому типизируется раздел). Хранится в таблице SysModuleEdit.
ConfigurationEnums.CardStateV2 - режим работы с записью.
Может быть:
- добавление новой записи,
- редактирования существующий записи,
- копирование существующей записи.

"Демьяник Алексей" написал:Хранится в таблице SysModuleEdit.

А если база находится на серверах Террасофта?

Здравствуйте, Виталий!

В данном случае Вы можете воспользоваться решением "PT SQL Executor for bpm’online" от партнера "Программные технологии": https://marketplace.terrasoft.ru/app/49

Благодарю за советы, вот что у меня получилось(работает):
onCreateContactClick: function() {
this.openAddMiniPage({
entitySchemaName: "Contact",
valuePairs: this.getAddMiniPageDefaultValues(this.Terrasoft.GUID_EMPTY)
});
}
typeColumnValue еще можно узнать из отладчика.

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

Добрый день!

Насколько мощнее должен быть сервер, если планируется интеграция с сайтом (практически персональный кабинет) через ODATA? Считать количество одновременных посетителей как пользователей? Или есть дополнительные параметры?

Нравится

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

Здравствуйте, Владимир.

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

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

Определил метод OnGetProfileKey:

                public void OnGetProfileKey(IWindow Window, Value Key) {
                        if (ScrUtils.Assigned(dlData.Dataset)) {
                                Key.Value = __global.System.ExtractUSICode(dlData.Dataset.USI);
                        }
                }

В результате на одно окно сохраняется несколько профилей.

НО. при загрузке окна выполняется запрос без фильтрации по ключу и ВСЕГДА применяется первый профиль из выборки.

exec sp_executesql N'SELECT
        [tbl_ProfileData].[ID] AS [ID],
        [tbl_ProfileData].[XMLData] AS [XMLData]
FROM
        [tbl_ProfileData] AS [tbl_ProfileData]
WHERE
        ([tbl_ProfileData].[UserID] = @P1 AND
        [tbl_ProfileData].[ServiceID] = @P2)'
,N'@P1 varchar(38),@P2 varchar(38)','{42708305-508B-4975-B92D-2E7A695A82FA}','{43E4D9B2-2EC8-48EA-A1FE-0E1C1842E307}'

Нравится

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

Денис, о чём вообще речь? Где задаётся этот код и на каком языке он написан?
Можете описать свою задачу и вопрос подробнее?

В окне SelectData необходимо несколько профилей.
Сделал в соответствии с этим http://www.community.terrasoft.ru/developer/advice/3258, Профиль окна

Скрипт окна пишем на C#.

При открытии окна отловил запрос SqlProfiler'ом и увидел, что ключ не влияет на запрос.

И окно по факту не работает с несколькими профилями, хотя они нормально сохраняются в tbl_ProfileData.

P.S. UseProfile установлен в true

В Terrasoft 3.X не используется язык C#. Скрипты пишутся на JScript, а ядро написано на Delphi.

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

Вы можете реализовать нужную Вам логику программно, не используя профили и сторонние языки программирования.

как это сделать? Я сделал в соответствии с руководством. Однако не работает.

Вот пример с руководства:

Также предусмотрена возможность хранения нескольких профилей для одного окна. Данная возможность необходима для универсальных окон, которые используются для различных целей. Примером такого окна может быть окно wnd_SelectData, которое предназначено для выбора значений из любых справочников, и должно "помнить" свои настройки для каждого справочника. Для реализации этого механизма используется событие OnGetProfileKey окна, в котором разработчик может определить код профиля, с которым в данный момент должно работать окно.

Пример – Работа с несколькими профилями:

function wnd_WindowOnGetProfileKey(Window, Key) {
 
      if (Window.Tag = '') {
 
            Key.Value = 'ProfileKey1';
 
      }
 
      else {
 
            Key.Value = 'ProfileKey2';
 
      }
 
}

Я в качестве ключа использую USI Dataset'a

В руководстве не предусмотрена работа с C#.

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

Добрый день!
Хочу добавить дополнительный CheckBox в раздел Ваш профиль > Настройки уведомлений
Для этого я создал "замещающий клиентский модуль" с ссылкой на родительский объект NotificationSettingSchema и написал в него код:

define("NotificationsSettingsSchema", ["DesktopPopupNotification"],
 function(DesktopPopupNotification) {
  return {
   entitySchemaName: "NotificationsSettings",
   attributes: {
    "PopupsStateFlag2": {
      name: "PopupsStateFlag2",
      dataValueType: this.Terrasoft.DataValueType.BOOLEAN,
      type: this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
    }
   },
 methods: {},
 diff: [
  {
   "operation": "insert",
   "name": "PopupsStateCheckBoxContainer2",
   "parentName": "NotificationsSettingsContainer",
   "propertyName": "items",
   "values": {
   "itemType": this.Terrasoft.ViewItemType.CONTAINER,
   "wrapClass": ["check-box-container", "stateflag-container"],
   "items": []
  }
 }, {
      "operation": "insert",
      "parentName": "PopupsStateCheckBoxContainer",
      "propertyName": "items",
      "name": "PopupsStateCheckBox2",
      "classes": ["t-checkboxedit"],
      "wrapClass": ["t-checkboxedit"],
      "values": {
      "bindTo": "PopupsStateFlag2",
      "labelConfig": {
      "caption": {"bindTo": "Resources.Strings.PopupsState2"}
     }
    }
   }
  ]
 };
});

В настройках уведомлений появился CheckBox:

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

Нравится

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

Сохранять её в
1) Своей системной настройке (персональной для каждого пользователя)
2) Сделать простой объект с полями (id, sysuser, flag) и туда записывать/считывать булево значение для каждого пользователя.
Соответственно реализовать методы подтягивания/создания флага в, например, onEntityInitialized, и сохранения/апдейта в onSaved

"Варфоломеев Данила" написал:

Сохранять её в

1) Своей системной настройке (персональной для каждого пользователя)

2) Сделать простой объект с полями (id, sysuser, flag) и туда записывать/считывать булево значение для каждого пользователя.

Соответственно реализовать методы подтягивания/создания флага в, например, onEntityInitialized, и сохранения/апдейта в onSaved

Правильно ли я создал объект?

Как мне реализовать методы (может быть есть какой нибудь пример)
1) подтягивания/создания флага
2) сохранения/апдейта

Правильно, только измените тип UsrSysUser на GUID.
Архив с примерным кодом прикрепляю.

"Варфоломеев Данила" написал:

Правильно, только измените тип UsrSysUser на GUID.

Архив с примерным кодом прикрепляю.

Прикрепленный файлРазмер

notificationcode.rar
934 байта

При попытке переименовать UsrSysUser в GUID появляется ошибка
Ошибка сохранения: Имя "GUID" колонки "Колонка 2" должно начинаться с префикса "Usr"
назвал UsrGUID

Спасибо за код, Вы прям адаптировали его под меня!
Только вот хотел спросить в каком месте мне его разместить - в этом же замещающем клиентском модуле? Получается что запись и чтение полей БД происходит напрямую из JavaScript?

"Молчанов Антон Сергеевич" написал:Ошибка сохранения: Имя "GUID" колонки "Колонка 2" должно начинаться с префикса "Usr"

Вы сохраняете название колонки, а надо тип. Как это сделать прикрепил скрин в архиве. Название поля оставьте UsrSysUser, методы что я прикреплял вставить в methods.

На скрине в п.4 в свойствах - отобразить все

"Молчанов Антон Сергеевич" написал:Получается что запись и чтение полей БД происходит напрямую из JavaScript?

Да, с помощью esq

"Варфоломеев Данила" написал:
Молчанов Антон Сергеевич пишет:

Ошибка сохранения: Имя "GUID" колонки "Колонка 2" должно начинаться с префикса "Usr"

Вы сохраняете название колонки, а надо тип. Как это сделать прикрепил скрин в архиве. Название поля оставьте UsrSysUser, методы что я прикреплял вставить в methods.

На скрине в п.4 в свойствах - отобразить все

Молчанов Антон Сергеевич пишет:

Получается что запись и чтение полей БД происходит напрямую из JavaScript?

Да, с помощью esq

Прикрепленный файлРазмер

screenshot.rar
71.17 кб

Переименовал колонку назад в UsrSysUser, сделал у неё тип данных GUID
Вставил в methods методы которые Вы мне прислали
Добавил ссылку на метод click: {bindTo: "SetFlag"} (Наверное зря добавил?)
получилась такая конструкция:

define("NotificationsSettingsSchema", ["DesktopPopupNotification"],
 function(DesktopPopupNotification) {
  return {
   entitySchemaName: "NotificationsSettings",
   attributes: {
    "PopupsStateFlag2": {
      name: "PopupsStateFlag2",
      dataValueType: this.Terrasoft.DataValueType.BOOLEAN,
      type: this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
    }
   },
 methods: {
 
  setFlag: function() {
   var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "UsrTakeMail"});
   esq.addColumn("UsrSysUser");
   esq.addColumn("UsrFlag");
   esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
   "UsrSysUser", Terrasoft.SysValue.CURRENT_USER.value));
   esq.getEntityCollection(function(result) {
    if (result.success) {
     if (result.collection.getCount() > 0) {
      var flag = result.collection.collection.items[0].values.UsrFlag;
      this.set("PopupsStateFlag2", flag);
     } else {
      this.set("PopupsStateFlag2", false);
      this.insertMyValue(false);
     }
    }
   }, this);
  },
 
  insertMyValue: function(flag) {
   var insert = Ext.create("Terrasoft.InsertQuery", {rootSchemaName: "UsrTakeMail"});
   insert.setParameterValue("UsrSysUser", Terrasoft.SysValue.CURRENT_USER.value,
   Terrasoft.DataValueType.GUID);
   insert.setParameterValue("UsrFlag", flag, Terrasoft.DataValueType.BOOLEAN);
   insert.execute();
  },
 
  updateFlag: function() { 
   var flag = this.get("PopupsStateFlag2");
   var sup = Ext.create("Terrasoft.UpdateQuery", {rootSchemaName: "UsrTakeMail"}); 
   sup.filters.addItem(sup.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
   "UsrSysUser", Terrasoft.SysValue.CURRENT_USER.value));
   sup.setParameterValue("UsrFlag", flag, Terrasoft.DataValueType.BOOLEAN);
   sup.execute();
  },		
 
  init: function() {
   this.callParent(arguments);
   this.setFlag();
  },
 
  saveSettings: function() {
   this.callParent(arguments);
   this.updateFlag();
 }},
 diff: [
  {
   "operation": "insert",
   "name": "PopupsStateCheckBoxContainer2",
   "parentName": "NotificationsSettingsContainer",
   "propertyName": "items",
   "values": {
   "itemType": this.Terrasoft.ViewItemType.CONTAINER,
   "wrapClass": ["check-box-container", "stateflag-container"],
   "items": []
  }
 }, {
      "operation": "insert",
      "parentName": "PopupsStateCheckBoxContainer",
      "propertyName": "items",
      "name": "PopupsStateCheckBox2",
      "classes": ["t-checkboxedit"],
      "wrapClass": ["t-checkboxedit"],
      "values": {
      "bindTo": "PopupsStateFlag2",
      "labelConfig": {
      "caption": {"bindTo": "Resources.Strings.PopupsState2"}
      click: {bindTo: "SetFlag"}
     }
    }
   }
  ]
 };
});

Галочка стала сохраняться! Спасибо большое!!!
Нашел в MSSQL свою таблицу, вижу как при сохранении изменяется значение поля UsrFlag!
init и saveSettings это стандартные функции которые выполняются автоматический при инициализации и сохранении компонента (их нельзя переименовывать)?
А можно ли как нибудь запустить JS в режиме отладки?

Здравствуйте!
Может пригодится: https://academy.terrasoft.ua/documents/technic-sdk/7-9/otladka-klientsk…

"Молчанов Антон Сергеевич" написал:init и saveSettings это стандартные функции которые выполняются автоматический при инициализации и сохранении компонента (их нельзя переименовывать)?

init - да, saveSettings - нет, на эту функцию завязан клик кнопки сохранить. Обычно на страницах обработчик сохранения - метод save
"Молчанов Антон Сергеевич" написал:А можно ли как нибудь запустить JS в режиме отладки?

в коде пишете debugger; С открытой консолью вызываете функцию, где у вас прописан debugger.

"Зарицкий Олег" написал:

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

Может пригодится: https://academy.terrasoft.ua/documents/technic-sdk/7-9/otladka-klientsko...

Спасибо!

"Варфоломеев Данила" написал:
Молчанов Антон Сергеевич пишет:

init и saveSettings это стандартные функции которые выполняются автоматический при инициализации и сохранении компонента (их нельзя переименовывать)?

init - да, saveSettings - нет, на эту функцию завязан клик кнопки сохранить. Обычно на страницах обработчик сохранения - метод save

Молчанов Антон Сергеевич пишет:

А можно ли как нибудь запустить JS в режиме отладки?

в коде пишете debugger; С открытой консолью вызываете функцию, где у вас прописан debugger.

Добрый день!
Вставил debugger; в процедуру SetFlag()
Проверил код на ошибки, пишет - Forgotten 'debbuger' statement?
Так и должно быть?

Да это нормально, это не ошибка а предупреждение, а вообще данное ключевое слово не обязательно, вы и сами можете ставить точки останова в браузере, почитайте про отладку в браузере: https://learn.javascript.ru/debugging-chrome

"Максим Шевченко" написал:

Да это нормально, это не ошибка а предупреждение, а вообще данное ключевое слово не обязательно, вы и сами можете ставить точки останова в браузере, почитайте про отладку в браузере: https://learn.javascript.ru/debugging-chrome

Попробовал отлаживать через браузер, получается!
Подскажите а как в отладчике я могу увидеть, какие данные получает запрос с установленным фильтром?
Не могу понять почему у меня не происходит запись в ячейку

SaveFlag: function() {
 var flag = this.get("PopupsStateFlag2");
 var sup = Ext.create("Terrasoft.UpdateQuery", {rootSchemaName: "SysAdminUnit"});
 sup.filters.addItem(sup.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,"Id", Terrasoft.SysValue.CURRENT_USER.value));
 sup.setParameterValue("UsrTakeMailFlag", flag, Terrasoft.DataValueType.BOOLEAN);
 sup.execute();
}

Вы можете посмотреть на структуру объекта sup до sup.Execute. потом он переваривается компилятором в запрос к базе. Если надо посмотреть коллбек (выполнился update или нет), то:

sup.execute(function(response) {
     debugger; ///тут смотрите, что пришло в response
}, this);

"Молчанов Антон Сергеевич" написал:var sup = Ext.create("Terrasoft.UpdateQuery", {rootSchemaName: "SysAdminUnit"});

Смотреть какие и куда уходят данные можно на закладке Network браузера, там же, будет видно завершился ли запрос с кодом 200(успешно) или словил какую-то ошибку. Единственное, почитав тему с начала, я не понимаю зачем вы пытаетесь писать в SysAdminUnit, вы разве туда добавили колонку UsrTakeMailFlag? Вроде бы вам рекомендовали для этих целей создать развязочный объект UsrTakeMail в котором будут хранится соответствия пользователя настройке.

Так же рекомендуем для записи, чтения и изменения использовать esq а не UpdateQuery. Подробнее про esq почитайте здесь:
https://academy.terrasoft.ua/documents/technic-sdk/7-6-0/ispolzovanie-r…
Это цикл статей для использования esq именно в джаваскрипте, но для лучшего понимания принципов её работы, почитайте и про серверную реализацию, там приводятся результирующие sql запросы:
https://academy.terrasoft.ua/documents/technic-sdk/7-9/ispolzovanie-ent…

"Варфоломеев Данила" написал:

Вы можете посмотреть на структуру объекта sup до sup.Execute. потом он переваривается компилятором в запрос к базе. Если надо посмотреть коллбек (выполнился update или нет), то:

sup.execute(function(response) {

     debugger; ///тут смотрите, что пришло в response

}, this);

Теперь понятно:
"Текущий пользователь не имеет прав на объект "SysAdminUnit""
success : false

"Максим Шевченко" написал:

Вроде бы вам рекомендовали для этих целей создать развязочный объект UsrTakeMail в котором будут хранится соответствия пользователя настройке.

Всё верно, я сначала создал развязочный объект UsrTakeMail и сохранял настройку в нём
Но потом подумал чтобы не создавать новых таблиц лучше создать дополнительную колонку в существующей SysAdminUnit.
Я хочу завязать мою настройку "получать письма" со скриптом "Отправка email сообщения группе"

var emailSelect = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "SysAdminUnit");
var emailColumn = emailSelect.AddColumn("Contact.Email");
var groupId = ReadCaseData.ResultEntity.GetTypedColumnValue<Guid>("GroupId");
emailSelect.Filters.Add(emailSelect.CreateFilterWithParameters(FilterComparisonType.Equal, "[SysUserInRole:SysUser].SysRole", groupId));
var collection = emailSelect.GetEntityCollection(UserConnection);
IsNeedSendEmail = collection.Count > 0;
RecipientEmails = string.Empty;
foreach(var entity in collection) {
	var email = entity.GetTypedColumnValue<string>(emailColumn.Name); 
	if (!string.IsNullOrEmpty(email)) {
		RecipientEmails += string.Format("{0};", email);
	}
}
return true; 

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

"Молчанов Антон Сергеевич" написал:Подумал что если данные будут лежать в одной таблице, мне останется лишь добавить в скрипт дополнительный фильтр - который бы отобрал только тех пользователей у кого стоит галочка "Получать письма"

SysAdminUnit системная таблица, лучше её не дорабатывать. Создайте развязочную таблицу.

"Максим Шевченко" написал:
Молчанов Антон Сергеевич пишет:

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

SysAdminUnit системная таблица, лучше её не дорабатывать. Создайте развязочную таблицу.

Хорошо, понял!

Получается что запись и чтение полей БД происходит напрямую из JavaScript?

Да, с помощью esq

Хотел спросить - а нормально ли что запись и чтение БД происходит с клиентской стороны через ESQ?
Может правильнее было бы создать на стороне сервера процедуры записи и чтения, а клиентом просто вызывать эти процедуры?

Здравствуйте, Антон!

"Молчанов Антон Сергеевич" написал:

Хотел спросить - а нормально ли что запись и чтение БД происходит с клиентской стороны через ESQ?

ESQ - это инструмент, который обращается к DataService. Сама вычитка данных с учетом прав происходит на стороне сервера. Пользователю отображается результат, который отдал сервер приложения.

"Молчанов Антон Сергеевич" написал:

Может правильнее было бы создать на стороне сервера процедуры записи и чтения, а клиентом просто вызывать эти процедуры?

Так и происходит.

"Демьяник Алексей" написал:

Так и происходит.

Понятно!

Получилось!!!
Мне удалось связать созданную настройку пользователя "Получать письма" с процессом "Отправки email сообщения группе".

Коллеги помогите теперь разобраться как и куда сохраняется галочка "Включить всплывающие уведомления"?

файл NotificationSettingSchema.js который отвечает за отображение страницы с галочкой содержит методы:

setPopupsState: function() {
 var state = this.get("PopupsStateFlag");
 DesktopPopupNotification.setNotificationsState(state, this.goBack.bind(this));
},
 
initPopupsState: function() {
 DesktopPopupNotification.getNotificationsState(function(enabled) {
 this.set("PopupsStateFlag", enabled);
}, this);

То есть setPopupsState и initPopupsState вызывают функции из DesktopPopupNotification.js

var setNotificationsState = function(enabled, callback) {
 Terrasoft.utils.saveUserProfile(getProfileKey(), {
  Enabled: enabled
 }, false, callback);
};
var getNotificationsState = function(callback, scope) {
 var key = getProfileKey();
 Terrasoft.require(["profile!" + key], function(profile) {
  callback.apply(scope, [profile.Enabled]);
 }, scope);
};
var getProfileKey = function() {
 return "DesktopPopupNotification";
};

Получается что настройки галочки храниться где то в Profile, то есть непонятно в какой таблице. Как можно считать её значение со стороны сервера?

"Молчанов Антон Сергеевич" написал:Получается что настройки галочки храниться где то в Profile, то есть непонятно в какой таблице. Как можно считать её значение со стороны сервера?

Профайл это таблица SysProfileData а в ObjectData хранится собственно сама настройка:

Только данная колонка это HEX значение, а его нужно преобразовать вначале в JSON и вытаскивать уже из него что вас интересует.

"Максим Шевченко" написал:
Профайл это таблица SysProfileData а в ObjectData хранится собственно сама настройка:

Действительно Профаил храниться в таблице SysProfileData, спасибо!
Подскажите, а как преобразовать HEX значение в JSON?
Мне необходимо получить значения у которых "ObjectData = True"
Могу ли сделать преобразование и сравнение непосредственно в фильтре?

emailSelect.Filters.Add(emailSelect.CreateFilterWithParameters(FilterComparisonType.Equal, "[SysProfileData:Contact:Contact].ObjectData", "True"));

У меня получилось преобразовать HEX в JSON,

string MyString = Entity.SerializeToJson(entity);

Получаю в MyString строки вида:

{  "Entity": {    "SchemaUId": "84f44b9a-4bc3-4cbf-a1a8-cec02c1c029c",    "Contact_Email": "Admin@yandex.ru",    "SysProfileData_Contact_Contact_ObjectData": "eyJFbmFibGVkIjpmYWxzZX0="  }}

как теперь мне вытащить из него ObjectData и преобразовать его нормальное значение?

Опишите, пожалуйста, корректней бизнес задачу, т.к: "получить значения у которых "ObjectData = True"" некорректно, в колонке ObjectData как раз находится джсон в формате хекс, следовательно вам нужно делать запрос к таблице SysProfileData получать колонку ObjectData для нужных пользователей по нужному ключу.
Получив эти данные уже можно преобразовывать их из хекс в строку, а из строки (читать джсон) и вытаскивать из него значение Enabled-а.
Прямо в фильтре этого не сделать, только получать, и преобразовывать данные, а потом уже, к примеру, в массиве полученных данных, делать выборку.
Пример получения ObjectData в виде строки, но без каких либо доп. условий в БП:

var userConnection = Get("UserConnection");

var esq = new EntitySchemaQuery(userConnection.EntitySchemaManager, "SysProfileData");
esq.AddColumn("Key");
esq.AddColumn("ObjectData");

var entities = esq.GetEntityCollection(userConnection);

foreach (var entity in entities) {
var test = entity.GetColumnValue("ObjectData");
string result = System.Text.Encoding.UTF8.GetString((byte[])test);
throw new Exception(result);
}

"Максим Шевченко" написал:
var test = entity.GetColumnValue("ObjectData");

string result = System.Text.Encoding.UTF8.GetString((byte[])test);

Максим добрый день!
Это как раз то, что мне было нужно!
Спасибо Вам за развернутые ответы!

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