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

Нравится

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 комментарий

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

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

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

Добрый день!
Хочу добавить дополнительный 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);

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

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

Добрый день,

Не довольны стандартным почтовым сервисом BPM Online sales.

Есть вопросы по поводу синхронизации почты через IMAP.

Также по ряду причин не устраивает коннектор на маркет плейс.

Есть ли у разработчиков/клиентов аналогичные готовые решения?

Нравится

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

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

Ваши вопросы по поводу синхронизации почты через IMAP Вы можете адресовать на support@terrasoft.ru

Замечания или пожелания касательно SmartCloud Connect for bpm’online Вы можете адресовать партнеру Invisible Solutions.

Приветствую!

Можете пожалуйста указать список причин по которым коннектор вам не подходит?

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

Добрый вечер, подскажите, пожалуйста, как можно реализовать задачу с помощью бизнес-процессов: допустим, если активность была создана в чт после 17:00, то установить время завершения активности и запуск блока “Изменить данные” на след. день на в 11:00.

Нравится

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

Мария, добрый день!
Для решения задачи вам помогут такие свойства:
https://msdn.microsoft.com/ru-ru/library/system.datetime.dayofweek(v=vs…
https://msdn.microsoft.com/en-us/library/system.datetime.minute(v=vs.11…
Можно разделить Дату создания на составляющие и записать результат в параметры процесса.
1. Первый параметр (условно CreatedOnDayOfWeek) будет хранить день недели, когда создана активность.
Примечание! Можно получить день недели в виде числа: Convert.ToInt32(currentDateTime.DayOfWeek), где вместо currentDateTime - подставить параметр с датой создания активности
2. Второй параметр (условно Hour) будет хранить час.

Дизайен процесса:
1. Стартовый сигнал по добвлению активности.
2. Читать данные в активности, где Id = Пункт 1. Id
После пунтк 2 добавить условный поток. В условном потоке проверять: (CreatedOnDayOfWeek ==4) && (Hour> 17)
3. Изменить данные в активности, где Id = Пункт 2. Id. Установить новую дату завершения

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

Подскажите пожалуйста как сделать задание!

Добавить на страницу создания/изменения/просмотра контрагента поля на закладку «Основная информаци»: «Кол-во продаж» (целое число), «Средний чек» (дробное 4 знака после запятой), «Дата последней продажи» (дата без времени), «Потенциал» (список, выбор из справочника «Приоритет активности»)

Я добавляю "Замещающий пакет", указываю родительский объект "Контрагент", затем добавляю в Columns : Кол-во продаж» (целое число), «Средний чек» (дробное 4 знака после запятой), «Дата последней продажи» (дата без времени), «Потенциал» (список, выбор из справочника «Приоритет активности»)
Затем кликаю сохранить и опубликовать!
Как теперь сделать так, чтобы измененное состояния показывалось на сайте?

Нравится

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

Алексей, здравствуйте!

Вам необходимо отобразить добавленные поля на странице редактирования с помощью мастера разделов.

Обучающий видеоролик - https://www.youtube.com/watch?v=DLFjsAR2CbI
Статья на Академии - https://academy.terrasoft.ru/documents/sales-enterprise/7-9/master-razd…

Вильшанский Дмитрий,

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

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

Добрый день, как добавить аудиоплеер на страницу для прослушивания записей звонков из bpm . bpm 7.7

Нравится

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

Здравствуйте.
Возможность прослушивать записи звонков зависит от используемой интеграции. Поддерживается в Oktell и Webitel. Плеер там уже присутствует. Подробнее описано здесь: https://academy.terrasoft.ru/documents/sales-team/7-9/zapis-i-proslushi…

Попробуйте:

var element = document.createElement("audio");
element.addEventListener("click", function(e) { e.stopPropagation(); }, false);
element.autoplay = true;
element.controls = true;
element.src = /**сюда url ссылку на сурс(пр.: запись звонка в wav формате)**/;
element.style.marginLeft = "5px";
element.type = "audio/mpeg";
var actionsDiv = Ext.get("AudioContainer").dom;
var lastChild = actionsDiv.children[actionsDiv.childElementCount - 1];
if (lastChild) {
	actionsDiv.removeChild(lastChild);
}
actionsDiv.appendChild(element);

контейнер для элемента

{
	"name": "AudioContainer",
	"operation": "insert",
	"parentName": "Detail",
	"propertyName": "tools",
	"index": 2,
	"values": {
		"id": "AudioContainer",
		"items": [],
		"itemType": Terrasoft.ViewItemType.CONTAINER
	}
}

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

Попробуйте:

var element = document.createElement("audio");

element.addEventListener("click", function(e) { e.stopPropagation(); }, false);

element.autoplay = true;

element.controls = true;

element.src = /**сюда url ссылку на сурс(пр.: запись звонка в wav формате)**/;

element.style.marginLeft = "5px";

element.type = "audio/mpeg";

var actionsDiv = Ext.get("AudioContainer").dom;

var lastChild = actionsDiv.children[actionsDiv.childElementCount - 1];

if (lastChild) {

        actionsDiv.removeChild(lastChild);

}

actionsDiv.appendChild(element);

контейнер для элемента

{

        "name": "AudioContainer",

        "operation": "insert",

        "parentName": "Detail",

        "propertyName": "tools",

        "index": 2,

        "values": {

                "id": "AudioContainer",

                "items": [],

                "itemType": Terrasoft.ViewItemType.CONTAINER

        }

}


Данил не могли бы Вы выслать полный код

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

Попробуйте:

var element = document.createElement("audio");

element.addEventListener("click", function(e) { e.stopPropagation(); }, false);

element.autoplay = true;

element.controls = true;

element.src = /**сюда url ссылку на сурс(пр.: запись звонка в wav формате)**/;

element.style.marginLeft = "5px";

element.type = "audio/mpeg";

var actionsDiv = Ext.get("AudioContainer").dom;

var lastChild = actionsDiv.children[actionsDiv.childElementCount - 1];

if (lastChild) {

        actionsDiv.removeChild(lastChild);

}

actionsDiv.appendChild(element);

контейнер для элемента

{

        "name": "AudioContainer",

        "operation": "insert",

        "parentName": "Detail",

        "propertyName": "tools",

        "index": 2,

        "values": {

                "id": "AudioContainer",

                "items": [],

                "itemType": Terrasoft.ViewItemType.CONTAINER

        }

}


Данил не могли бы Вы выслать полный код

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

Добрый день.
Задача: при сохранении карточки контрагента производить проверку - а не существует ли уже в системе контрагента с таким же значением поля UsrParametr1.
Я переопределила метод save() в карточке контрагента. Произвожу поиск с помощью EntitySchemaQuery - если в качестве результата мне вернулось кол-во записей > 1, значит запись с таким UsrParametr1 существует и я просто вывожу сообщение и не сохраняю карточку контрагента.
Но если же же записей 1, то я должна вызвать базовый метод save, который произведет сохранение карточки. При вызове this.callParent(arguments); появляется ошибка и карточка не сохраняется.
Подскажите, как решить данную проблему?

Переопределенный метод save():

save: function() {
        var param = this.get("UsrParametr1");
        var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                rootSchemaName: "Account"
        });
        esq.addColumn("UsrParametr1", "UsrParametr1");
        var filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrParametr1", param);
        esq.filters.add("filter", filter);
        esq.getEntityCollection(function(result) {
                if (!result.success) {
                        this.showInformationDialog("Ошибка");
                        return;
                }
               
                if (result.collection.collection.items.length > 1)
                {
                        this.showInformationDialog("Нельзя сохранить");
                        return;
                }
                this.callParent(arguments); // не отрабатывает, появляется ошибка
        }, this);
}

Нравится

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

Добро пожаловать в мир асинхронных вычислений!
Для наглядности:

esq.getEntityCollection(callback, scope);

т.е программа заходит в функцию save, бежит до esq.getEntityCollection, и после него функция save завершается. Далее спустя некоторое время приходит callback, вызывается функция с параметром result

function(result) {
                if (!result.success) {....

Беда в том, что внутри неё ни о каком callParent() и речи быть не может. (ибо вы находитесь внутри самописной функции, у неё нет родителя для вызова).

В качестве дико кривого варианта:

save: function(parameter) {
if (!parameter) {this.checkField()}
else {this.callParent(arguments)}
}
 
checkField: function() {
//тут esq запрос и в callback-е, если все условия сходятся (записей < 1 в вашем случае), вызываете this.save(true);
}

или

сделать по-умному: в объекте создать событийный подпроцесс (перед сохранением или проверка записи, тут надо примеры в конфигурации посмотреть), в подпроцессе проверять условия и в зависимости от них принимать решение... Но это все скучно, к тому же придется кодить на C#.

Как-то так. Костыли - наше все.

Лучше в Validation это делать, наверное

Добрый день. В вашем случае надо переопределить getParentMethod, чтобы callParent не вызывался.
Рабочий код будет выглядеть следующим образом:

getParentMethod: function() {
	var method,
		superMethod = (method = this.getParentMethod.caller) && (method.$previous ||
			((method = method.$owner ? method : method.caller) &&
			method.$owner.superclass[method.$name]));
	return superMethod;
},
 
 
save: function() {
		var parentSave = this.getParentMethod();
		var parentArguments = arguments;
 
        var param = this.get("UsrParametr1");
        var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                rootSchemaName: "Account"
        });
        esq.addColumn("UsrParametr1", "UsrParametr1");
        var filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrParametr1", param);
        esq.filters.add("filter", filter);
        esq.getEntityCollection(function(result) {
                if (!result.success) {
                        this.showInformationDialog("Ошибка");
                        return;
                }
 
                if (result.collection.collection.items.length > 1)
                {
                        this.showInformationDialog("Нельзя сохранить");
                        return;
                }
                //this.callParent(arguments); // не отрабатывает, появляется ошибка
				parentSave.apply(this, parentArguments);
        }, this);
}

Елена, в Вашем первоначальном коде, достаточно в коллбэкке esq-запроса, вызывать не this.callParent(argumеnts); а непосредственный метод "save" у контекста. При необходимости сохранив в текущем контексте аргументы изначально передаваемые в метод, и установив специальный флаг реагируя на повторный вызов.

save: function() {
    //Проверка на повторный вызов из асинхронной функции запроса.
    if (this.saveRecallFlag) {
        //сбросим флаг повторного вызова
        this.saveRecallFlag = false;
        //стандартное сохранение
        this.callParent(arguments);
    } else {
        //Если нет - выполняем логику:
        var param = this.get("UsrParametr1");
        var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                rootSchemaName: "Account"
        });
        esq.addColumn("UsrParametr1", "UsrParametr1");
        var filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrParametr1", param);
        esq.filters.add("filter", filter);
        //Перед асинхронным вызовом, сохраним набор аргументов с которым был вызван метод в текущем контексте
        //Мы именно клонируем массив, т.к. в момент вызова асинхронной функции, псевдомасив arguments будет
        //содержать параметры вызова коллбэка.
        this.saveArgumentsRecallBuff = _(arguments).clone();
        //Установим в текущий контекст специальный флаг, который позволит проигнорировать логику проверки
        //при повторном вызове
        this.saveRecallFlag = true;
        esq.getEntityCollection(function(result) {
                if (!result.success) {
                        this.showInformationDialog("Ошибка");
                        return;
                }
 
                if (result.collection.collection.items.length > 1)
                {
                        this.showInformationDialog("Нельзя сохранить");
                        return;
                }
                this.save(this.saveArgumentsRecallBuff); // не отрабатывает, появляется ошибка
        }, this);
    }
}
Показать все комментарии

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

Версия 7.9.

На странице контрагента (также контакта и т.д.) есть деталь Адреса. При добавлении адреса открывается страница добавления. Её же можно открыть и при изменении адреса.

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

Как в этом случае войти в дизайнер, или как ещё можно добавить поле (только через diff в схеме, или ещё какие-то способы есть?)

Нравится

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

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

Нравится

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

Здравствуйте, Михаил.

Вам необходимо:

1) Заместить схему карточки на которой выведена данная деталь.
2) Добавить в секции diff для данной детали свойство visible ссылающееся виртуальный атрибут булевого типа имеющий значение по умолачанию true.
3) Заместить схему детали и добавить обработчик события изменения атрибута GridData

init: function() {
   this.callParent(arguments);
   this.on("change:GridData", function(){
      //some code
   }, this);
}

4) В обработчике (пункт 3) проверять количество элементов в GridData. Если больше нуля - публиковать сообщение.

5) В схеме карточки основываясь на сообщении изменять значение виртуального атрибута.

Сообщения sandbox подробно обсуждались тут.

"Мотков Илья" написал:

Здравствуйте, Михаил.

Вам необходимо:

1) Заместить схему карточки на которой выведена данная деталь.

2) Добавить в секции diff для данной детали свойство visible ссылающееся виртуальный атрибут булевого типа имеющий значение по умолачанию true.

3) Заместить схему детали и добавить обработчик события изменения атрибута GridData

init: function() {

   this.callParent(arguments);

   this.on("change:GridData", function(){

      //some code

   }, this);

}

4) В обработчике (пункт 3) проверять количество элементов в GridData. Если больше нуля - публиковать сообщение.

5) В схеме карточки основываясь на сообщении изменять значение виртуального атрибута.

Сообщения sandbox подробно обсуждались тут.


А есть явный какой-то пример в исходниках чтобы на него акцент делать?

Подобного примера в конфигурации нет. Однако почти в каждой схеме есть примеры создания атрибутов, привязки свойства visible к методу или же атрибуту. Точно так же sandbox повсеместно используеьтся в системе.

К примеру атрибут можно jобьявить следующим образом:

attributes: {
	IsEmailVisible: {
		dataValueType: this.Terrasoft.DataValueType.BOOLEAN,
		type: this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
		value: true
	}
},

Пример привязки видимости детали Email к атрибуту:

{
	"operation": "merge",
	"name": "Email",
	"values": {
		"visible": {
			bindTo: "IsEmailVisible"
		}
	}
},

"Мотков Илья" написал:

4) В обработчике (пункт 3) проверять количество элементов в GridData. Если больше нуля - публиковать сообщение.


А проверять DataGrid по средствам esq или как-то иначе можно? Или можно как то читать то, что находится на самой детали, чтобы каждый раз в базу не ходить?

GridData это атрибут схемы детали. Получить его можно через код:

var gridData = this.get("GridData");

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

В целом GridData отвечает за реестр детали.

"Мотков Илья" написал:

GridData это атрибут схемы детали. Получить его можно через код:

var gridData = this.get("GridData");

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

В целом GridData отвечает за реестр детали.

init: function() {
	this.callParent(arguments);
	var gridData = this.getGridData();
	this.reloadGridColumnsConfig(true);
	if (gridData && gridData.getCount() > 0) {
		this.sandbox.publish("MessageGridCount", {
			stateObj:
				{
					valuePairs: [{name: "DataGridCount", value: gridData.getCount()}]
				}
		});
	}
}

Поле gridData в консоли указывает что undefined. Как с этим бороться? За пример брал реализацию в BaseGridDetailV2.
Так же ваш пример (var gridData = this.get("GridData");) тоже самое выдает в консоли.

Попробуйте получать GridData в методе после его загрузки:

afterLoadGridData: function() {
this.callParent(arguments);
var gridData = this.get("GridData");
},

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

Попробуйте получать GridData в методе после его загрузки:

afterLoadGridData: function() {

this.callParent(arguments);

var gridData = this.get("GridData");

},


Попробовал, но тоже никак.
http://prntscr.com/dy1c0z

Получить значение GridData можно обратившись к атрибуту Collection (this.get("Collection")) или же вызвав метод getGridData который в свою очередь обратится к атрибуту Collection и вернет результат.

Получать актуальное количество записей в GridData возможно заместив обработчик события dataLoaded атрибута Collection. Пример:

onGridLoaded: function() {
this.callParent(arguments);
var count = this.getGridData().collection.items.length;
}

Прошу прощения за неточность. Публиковать сообщение не нужно, по скольку логика добавления записи (как собственно и кнопка +) расположена в BaseGridDetalV2 (элемент AddRecordButton).

"Мотков Илья" написал:

Прошу прощения за неточность. Публиковать сообщение не нужно, по скольку логика добавления записи (как собственно и кнопка +) расположена в BaseGridDetalV2 (элемент AddRecordButton).


Спасибо, но я заодно и с песочницей разобрался, на будущее.

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