Добрый день. Возник такой вопрос - как можно добавить больше категорий для элемента Отложить напоминание (чтобы было больше вариантов для переноса напоминания, уведомления - смотреть прикрепленный файл)
В схеме ReminderNotificationsSchema реализована описанная Вами логика, а именно - в методе getNotificationActionButtonMenuItems. Вы можете заместить указанную схему и переопределить метод, добавив в него необходимые значения.
Данная идея уже зарегистрирована у команды разработки для реализации в следующих версиях системы. Номер проблемы 3762
Если Вы хотите реализовать перенос своими силами, для решения данного вопроса Вы можете воспользоваться базовым функционалом системы в виде бизнес-процессов, создав свой процесс. В данном процессе необходимо первым элементом вычитать создаваемую продажу, вторым чтением данных ту, из которой создается, третьим элементом "чтение данных" вычитать деталь "продукт в продаже" и четвертым элементом "добавление данных" перенести все продукты. Перед построением своего процесса рекомендуем ознакомится с руководством пользователя по работе с бизнес-процессами: https://academy.terrasoft.ua/documents/technic-bpms/7-9/obzor-funkciona…
Мария, благодарю за своевременный ответ. Хотел уточнить один момент. При создании данного бизнес-процесса какие отличия будут в первом чтении данных продажи от второго чтения данных продажи (как мне в свойствах указать, что читаю данные из копируемой продажи и исходной продажи)?
"Мария Ватулина" написал:
В данном процессе необходимо первым элементом вычитать создаваемую продажу, вторым чтением данных ту, из которой создается, третьим элементом "чтение данных" вычитать деталь "продукт в продаже" и четвертым элементом "добавление данных" перенести все продукты.
Решение с процессом корректно, однако реализация должна быть другой. Есть два варианта:
1) Требующий навыков программирования на JS (для создания действия, которое будет вызывать процесс из раздела)
2) Не требующий навыков программирования.
В первом варианте:
Создайте параметр с типом "Уникальный идентификатор". Назовем его RecordId
Общая структура процесса
Начальный элемент
Элемент добавить данные в режиме выборки. Добавляем данные в объект "Продажа". Выборка по объекту "Продажа". Фильтр выборки Id = [#RecordId#]
Элемент добавить данные в режиме выборки. Добавляем данные в объект "Продукт в продаже". Выборка по объекту "Продукт в продаже". Фильтр выборки Продажа = [#RecordId#]
Конец процесса
Также можно вначале процесса добавить проверку, что параметр RecordId != Guid.Empty (проверка, что процесс запущен по записи, а не вручную).
Дополнительно нужно создать действие в разделе, который вызовет указанный процесс по выделенной записи. Например, можно создать кнопку в разделе. Подробнее можно найти по ссылке: http://www.community.terrasoft.ru/forum/topic/14042
В втором варианте:
Общая структура процесса
Начальный элемент
Автогенерируемая страница с полем выбора из справочника "Продажа"
Элемент добавить данные в режиме выборки. Добавляем данные в объект "Продажа". Выборка по объекту "Продажа". Фильтр выборки Id = [#Автогенерируемая страница.Продажа#]
Элемент добавить данные в режиме выборки. Добавляем данные в объект "Продукт в продаже". Выборка по объекту "Продукт в продаже". Фильтр выборки Продажа = [#Автогенерируемая страница.Продажа#]
Конец процесса
Такая реализация требует дополнительного действия пользователя.
getCurrencyRate:function(LogCurrencyRow){ var LogCurrencyRate =0;
var esq = Ext.create("Terrasoft.EntitySchemaQuery",{rootSchemaName:"CurrencyRate"});
esq.addColumn("Rate"); var _tomorrow =new Date();
_tomorrow.setDate(_tomorrow.getDate()+1); var _yesterday =new Date();
_yesterday.setDate(_yesterday.getDate()-1);
Не могу понять почему
esq1.getEntityCollection(function(response)
в if (response && response.success) { не попадает
и дальше проходит по коду.
Что не так?
Вы написали не синхронный код и ожидаете от него синхронного поведения. Функция, передаваемая в метод getEntityCollection вызывается асинхронно после ответа от базы данных. Она будет вызвана в другом контексте и уже после того как метод getCurrencyRate отработает.
Вам стоит смотреть в сторону использования атрибутов или же Terrasoft.chain. Атрибуты помогут с кешированием значения. Terrasoft.chain позволит создать цепочку вызовов callback функций.
Также, судя по предоставленному коду, Вам достаточно вы функции обратного вызова вызывать следующий метод в правильном контексте. Контекст можно задать функцией bind. Упрощенный пример:
Мы реализовали действие в разделе Юр. лиц, которое инициирует загрузку данных из сервиса СПАРК и записывает их в базу с помощью хранимой процедуры. Возникла проблема, связанная с тем, что по загруженным Юр. лицам не запускаются процессы (стартовые события процессов - сигнал добавление/изменение).
Стартовые сигналы не реагируют на прямые запросы к БД (добавление/изменение/удаление записей).
Сигналы срабатывают если запрос выполняется через EntitySchemaQuery - https://academy.terrasoft.ua/documents/technic-sdk/7-9/rabota-s-dannymi
Вы можете решить вашу задачи с помощью триггеров в БД или создать процесс, который будет периодически запускаться с помощью планировщика и обрабатывать интересующие записи.
Коллеги, а триггеры в БД имеется в виду на добавление/изменение?
Если у нас будет обновление поля через ESQ и одновременно будет создан триггер на изменение этого поля в БД, не будет ли двойного срабатывания стартового события одного и того же процесса?
Коллеги, а триггеры в БД имеется в виду на добавление/изменение?
Если у нас будет обновление поля через ESQ и одновременно будет создан триггер на изменение этого поля в БД, не будет ли двойного срабатывания стартового события одного и того же процесса?
Как было сказано ранее - если операции происходит на уровне сервера БД (процедуры, триггеры, прямые запросы в БД), то процессы срабатывать не будут. По этой причине процесс сработает только по запросу ESQ - триггеры не запустят второй экземпляр процесса.
Все же обсуждение выше о том что прямая работа в бд, включая работу по созданию или удалению или модификации сущностей бд, вкючая тригеры бд, никак не могут запускать БП, и нет никакого механизма тригеров бд, которые будут запускать события бп. это может делать только bpmonline, работайте над созданием данных на уровне схем и сущностей, как было указано выше, пример:
var entitySchemaManager = _userConnection.GetSchemaManager("EntitySchemaManager") as EntitySchemaManager;
var activityParticipantSchema = entitySchemaManager.GetInstanceByName("ActivityParticipant");
var activityParticipant = activityParticipantSchema.CreateEntity(_userConnection) as ActivityParticipant;
activityParticipant.SetDefColumnValues();
activityParticipant.ActivityId = _currentEmailActivityId;
activityParticipant.ParticipantId = contactId;
activityParticipant.RoleId = roleId;
activityParticipant.Save();
Подскажите пожалуйста, можно ли в bpm настроить интервал синхронизации с почтой? Например, подключено несколько почтовых ящиков (ящик1@mail.ru, ящик2@mail.ru). Мне нужно, чтобы письма с ящика ящик1@mail.ru синхронизировались в течении 1 минуты, а ящик2@mail.ru - 60 минут.
Присутствует системная настройка "Интервал синхронизации с почтовым ящиком", но эта настройка применяется, как я понимаю, для всех ящиков.
В базовой версии приложения установить различный период синхронизации для почтовых ящиков пользовательскими средствами нельзя.
Уточните, пожалуйста, какой бизнес-кейс необходимо покрыть данными изменениями?
Существует ли возможность инициировать проверку всех установленных пакетов на предмет наличия обновлений и установку оных в случае обнаружения ?
При установке пакетов было замечено что система самостоятельно реагирует на наличие неразрешенных зависимостей, и в случае если зависимости присутствуют в подключенных хранилищах - то зависимости устанавливаются автоматически, в том числе и обновляются уже установленные зависимости если для них есть изменения. Напрашивается возможность запускать подобный механизм принудительно но для проверки всех установленных пакетов.
В текущих версиях системы отстутствует механизм одновременного обновления всех пакетов. Вы можете выполнять обновление из хранилища только каждого пакета в отдельности. При выполнении данного действия будет запущен процесс обновления выбранного пакета и всех его пакетов-зависимостей из активных хранилищ системы контроля версий.
В типовом окне выбора как и положено у модальных окон - присутствует элемент управления модальным окном "закрыть". в простонародии: "крестик" Вопрос: Существует ли какая либо конфигурационная настройка на этот счет для вызова окна через openLookup(config)
Т.к. в нашем случае бизнес-логика в идеале предусматривает безусловную реакцию пользователя на предложенный выбор, хотелось бы вместо обработки результатов, просто исключить у пользователя "далее-далее-крестик-крестик-готовщика" возможность закрыть это окно.
PS: Отключение кнопки закрытия окна, тоже не silver bullet т.к. пользователь просто может нажать "выбрать" - ничего на самом деле не выделив. И как сопутствующий вопрос - можно ли регулировать это поведение в типовом окне выбора, таким образом чтобы кнопка "Выбрать" например была не активной пока пользователь не произведет выбор, или например генерировала уведомление об обязательности выбора значения ?
Здравствуйте,
Вы конечно можете написать глобальный css стиль который скроет крестик, или переписать LookupPageViewGenerator для блокировки кнопки выбор. Но логичнее наверно прописать обязательность заполнения лукапного поля, на странице, на которой данный лукап и выбирается. Безусловно или по условию: https://academy.terrasoft.ru/documents/technic-sdk/7-8/pravilo-bindpara…
В типовом окне выбора как и положено у модальных окон - присутствует элемент управления модальным окном "закрыть". в простонародии: "крестик" Вопрос: Существует ли какая либо конфигурационная настройка на этот счет для вызова окна через openLookup(config)
Т.к. в нашем случае бизнес-логика в идеале предусматривает безусловную реакцию пользователя на предложенный выбор, хотелось бы вместо обработки результатов, просто исключить у пользователя "далее-далее-крестик-крестик-готовщика" возможность закрыть это окно.
PS: Отключение кнопки закрытия окна, тоже не silver bullet т.к. пользователь просто может нажать "выбрать" - ничего на самом деле не выделив. И как сопутствующий вопрос - можно ли регулировать это поведение в типовом окне выбора, таким образом чтобы кнопка "Выбрать" например была не активной пока пользователь не произведет выбор, или например генерировала уведомление об обязательности выбора значения ?
Здравствуйте,
Вы конечно можете написать глобальный css стиль который скроет крестик, или переписать LookupPageViewGenerator для блокировки кнопки выбор. Но логичнее наверно прописать обязательность заполнения лукапного поля, на странице, на которой данный лукап и выбирается. Безусловно или по условию: https://academy.terrasoft.ru/documents/technic-sdk/7-8/pravilo-bindpara…
Обязательность поля для заполнения в данном случае не очень подходит, вернее базовая логика обработки "не заполненности" обязательных полей- т.к. в случае обязательности поля - пользователю выводится сообщение о том, что не заполнено одно или несколько обязательных полей, перечисляются их наименования, и сохранение карточки прерывается, после чего карточка остается в режиме ввода данных т.е. подразумевается что пользователь найдет указанные в сообщении поля, заполнит их и нажмет "Сохранить".
Во-первых работать с карточкой невозможно пока не закроешь оповещение в котором указаны поля для заполнения. (А стало быть пользователю надо их запомнить или записать :cry: в идеале такие уведомления надо делать интегрированными в UI а не модальной нотификацией, так как сделаны предупреждения и ошибки в конфигураторе например, текст которых остается видимым и с интерфейсом можно продолжить работу)
Во-вторых в некоторых карточках очень перегруженный интерфейс и поиск самого поля которое необходимо заполнить во множестве вкладок и т.д. - отнимает время у сотрудника (если это горячая линия, то эти 10-20 секунд в конечном итоге превращаются в минуты которые никому из клиентов ждать не хочется)
В третьих, если у Вас бизнес-логика подразумевает фиксацию совершения какого либо действия во времени, то в данном случае Вам потребуется вводить дополнительную проверку в логику сохранения карточки (т.к. фактически заполнение произойдет когда-то потом а не по нажаию кнопки) а не совершения какого либо действия чтобы отметить время совершения.
Ну и в конце концов - это просто удобно для пользователя, чтобы система предлагала ему выбор автоматически, если он что-то забыл.
Магической системной настройки, убирающей отображение кнопки "закрыть" нету, необходимо переписывать логику самого модального окна. Вам стоит обратить внимание на 3 схемы: LookupPage, LookupPageViewGenerator и LookupPageViewModelGenerator. Для удаления кнопки закрыть - Вам стоит смотреть в сторону удаления кода генерации closeIconContainer в LookupPageViewGenerator. Для изменения логики кнопки "Выбрать" - переопределить конфиг для SelectButton в LookupPageViewGenerator, а также добавить логику в LookupPageViewModelGenerator.
Доводилось ли кому реализовывать функционал для сложных взаимосвязей в холдинге?
Конкретно, несколько задач:
1) У одной компании может быть несколько "материнских компаний" - акционеров.
2) Между компаниями могут быть дополнительные взаимосвязи
3) В итоге на связях должны и присутствовать контакты - бенефициары
4) На схеме необходимо отображать и другие типы связей, а не только "holding - affiliate)
Доброго времени суток! Требует помощь с пониманием как работает TimezoneContainer у контакта, для того чтобы по аналогии сделать её для контрагента. Кто с таким сталкивался, прошу помощи.
define("AccountPageV2", ["TimezoneGenerator", "TimezoneMixin"], function(){return{
entitySchemaName:"Account",
mixins:{
TimezoneMixin:"Terrasoft.TimezoneMixin"},
methods:{
onEntityInitialized: function(){this.callParent(arguments);this.mixins.TimezoneMixin.init.call(this);},
onDetailChanged: function(detail){this.callParent(arguments);if(detail.schemaName==="AccountAddressDetailV2"){this.updateTimezone();}},
updateTimezone: function(){this.mixins.TimezoneMixin.init.call(this);},
setContactTimeConfig: function(accId, callback, scope){//метод из TimeZoneMixin, его надо расковырять
var func = function(contactTimeConfig){
var isValid =this.isConfigValid(contactTimeConfig);if(isValid){this.set("ContactTimeConfig", contactTimeConfig);if(callback &&this.Ext.isFunction(callback)){
callback.call(scope);}}else{this.log(Resources.localizableStrings.ContactTimeConfigInvalidFormatException,
Terrasoft.LogMessageType.WARNING);}};this.getAccountTimeZone(func, accId);},
getAccountTimeZone: function(callback, accId){
var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName:"AccountAddress"});
esq.addColumn("City.TimeZone.Name", "TZName");
esq.addColumn("City.TimeZone.Offset", "Offset");
esq.addColumn("City.Name", "CityName");
esq.filters.addItem(esq.createColumnFilterWithParameter(3, "Account", accId));
esq.getEntityCollection(function (result){
var info = result.collection.collection.items[0].values;//По-идее нужно лезть в кучу миксинов/утилит/хелперов с сервисами, но можно и так вытащить инфу по городу. Тут я беру 1 попавшийся из AccountAddress. Можно дополнить фильтрами
var offset = info.Offset==="GMT"?0: parseInt(info.Offset.split("GMT")[1].split(":")[0]);
var time=new Date(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDate(), new Date().getUTCHours(), new Date().getUTCMinutes(), new Date().getUTCSeconds());time.setUTCHours(time.getUTCHours()+ offset);
var contactTimeConfig ={
equals:true,
location: info.CityName,
minutesOffset: offset*60,
time:time,
timeZone: info.TZName};this.callback.call(this.scope, contactTimeConfig);}.bind({callback: callback, scope:this}));}},
diff:[{"operation":"insert",
"name":"TimeZoneContainer",
"parentName":"AccountPhotoContainer",
"propertyName":"items",
"values":{"itemType": Terrasoft.ViewItemType.CONTAINER,
"generator":"TimezoneGenerator.generateTimeZone",
"wrapClass":["timezone-container"],
"visible":true,
"timeZoneCaption":{"bindTo":"TimeZoneCaption"},
"timeZoneCity":{"bindTo":"TimeZoneCity"},
"tips":[]}}]};});
Ну и ещё надо навесить немного стилей (пр. убрать часы под контейнер с обогащение данных). Но мне лень)