Добрый день!
Есть задача добавить представление в разделе, в котором будет редактируемый реестр другого объекта с собственными фильтрами (фильтры аналогичны с фильтрами раздела).
Подскажите, пожалуйста, как реализовать данный функционал?

Нравится

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

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

Правильно ли я понимаю, что Вы хотите создать еще одно представление раздела, выведя в реестр детали, и добавив в созданное представление "Фильтр", который будет фильтровать записи на деталях?

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

Добрый день!
Вашу задачу нужно разделить на 2 этапа:
1. Создать представление
2. Создать свой модуль отображения реестра

По 1-му:
Начать нужно искать с BaseSection, в котором есть функция initDataViews(). Далее по аналогии с, например, представлением "Аналитика"

По 2-му:
Вам нужно создать свой модуль, который будет отображать что угодно (ваш реестр, графики...). После этого проследите как работает функция LoadView из BaseSection, на примере того же представления Аналитика

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

Добрый день,

Хотел бы сделать так, чтобы при создании лида, при выборе контакта в поле "Ответственный" подставлялось соответствующее значение аналогичного поля из выбранного контакта. Пытался сделать это созданием замещающей страницы LeadSection (в ней, я так понимаю, происходит создание лидов) и добавлением туда приблизительно следующего кода:

attributes: {
        'Owner1' : {
                dependencies: [
                {
                        columns: ["Contact"],
                        methodName: "setOwnerToContact"
                }
                ]
        }
},
methods: {
        setOwnerToContact: function () {
                var Contact = this.get('Contact');  
                if (Contact != null) {
                        var esq = Ext.create('Terrasoft.EntitySchemaQuery', {
                                rootSchemaName: "Contact"
                        });
                        var self = this;
                        esq.addColumn("Id");
                        esq.addColumn("Owner");
                        esq.filters.add("Id", Terrasoft.createColumnFilterWithParameter(
                                Terrasoft.ComparisonType.EQUAL, "Id", Contact.value));
                        esq.getEntityCollection(function(result) {
                                if (result.success) {
                                        Terrasoft.each(result.collection.getItems(), function(item) {
                                                self.set("Owner1", item.get("Owner"));
                                        });
                                }
                        });
                }
        }
},

Не сработало. Подскажите пожалуйста, как это было бы правильно сделать?

Нравится

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

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

Не совсем верно. LeadSectionV2 - это страница раздела, а LeadPageV2 - страница редактирования лида. Соответствующую приблизительную:smile: логику Вам необходимо реализовать в LeadPageV2.

Скину несколько полезных ссылок:

"Демьяник Алексей Олегович" написал:LeadSectionV2 - это страница раздела, а LeadPageV2 - страница редактирования лида.

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

"Кулагин Дмитрий Леонидович" написал:
Демьяник Алексей Олегович пишет:

LeadSectionV2 - это страница раздела, а LeadPageV2 - страница редактирования лида.

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

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

Section - это представление раздела, Page - страница редактирования. На странице редактирования Вы создаете как новые записи, так и редактируете существующие.

Данную логику необходимо реализовывать в Page.

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

Добрый день.
Задача следующая:
Необходимо запускать БП каждую неделю в определённое время.
Реализовал:
В качестве первого элемента БП использую скрипт, в котором запускаю следующий код:

//delete previous job
Scheduler.AppScheduler.RemoveJob(
        "StartSxScheduledMeetingJob",
        "SxScheduledMeetingGroup"
);

//set new job
int minutelyInterval = 10080; //7 days (minutes)
Scheduler.AppScheduler.ScheduleMinutelyProcessJob(
        "StartSxScheduledMeetingJob",
        "SxScheduledMeetingGroup",
        "SxScheduledMeeting",
    "Default",
        "Supervisor",
        minutelyInterval);

После чего выполняются остальные элементы БП.
Проблема в том, что БП начал запускаться не через 7 дней (эквивалент 10080 минут), а каждую секунду.
При анализе содержимого Таблиц с префиксом QRTZ выявлено, что запись была добавлена в следующие таблицы
QRTZ_FIRED_TRIGGERS
QRTZ_JOB_DETAILS
QRTZ_TRIGGERS
QRTZ_SIMPROP_TRIGGERS
Чем вызвано подобное поведение планировщика?
И как корректно реализовать такую задачу?

Нравится

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

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

Попробуйте сделать следующим образом:

string schedulerJobGroupName = "StartSxScheduledMeetingJob"
string jobProcessName = "SxScheduledMeeting";
string schedulerJobName = "StartSxScheduledMeetingGroup";
int startOffset = 648000;
AppScheduler.RemoveJob(schedulerJobName, schedulerJobGroupName);
var job = AppScheduler.CreateProcessJob(schedulerJobName, schedulerJobGroupName, jobProcessName, UserConnection.Workspace.Name, UserConnection.CurrentUser.Name);
var trigger = new SimpleTriggerImpl(schedulerJobName + "Trigger", schedulerJobGroupName, DateTime.UtcNow.AddSeconds(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);
return true;

"Демьяник Алексей Олегович" написал:int startOffset = 648000;

Вы здесь укаываете интервал в секундах?
Если да то там ошибка
7 дней = 604800 сек.

Прошу прощения за опечатку.

Верно,
Если необходимо установить интервал в 7 дней - следует указать значение 604800.

А из-за чего происходит указанная мной ошибка при использовании ScheduleMinutelyProcessJob , когда БП перезапускается каждую секунду вместо раза в 7 дней?

Добрый день!

Вероятно, проблема связана с тем, что в коде не указано return true;

Указан. Я его не указал в обращении, т.к. он не относится к вопросу. Могу предоставить md-файл на анализ

Добрый день!

Предоставьте, пожалуйста. Укажите также версию приложения.

Версия:
7.5.0.1422_SalesOmnichannel_Marketing_CustomerEngagementCenter_Softkey_MSSQL_RUS

Игорь, скажите, пожалуйста, мое решение подошло для решения Вашей задачи?

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

Просьба указать наиболее корректный вариант решения данной задачи, предложенный выше Демьяник Алексеем (Комментарий #1) или мой.

Добрый день!

Оба варианта корректные, Алексей предложил практический вариант применения планировщика.

"Демьяник Алексей Олегович" написал:

Игорь, скажите, пожалуйста, мое решение подошло для решения Вашей задачи?

Ругается на класс SimpleTriggerImpl.
Какое пространство имён мне нужно добавить в Using?
И не лучше ли в моём случае использовать CronTriggerImpl (только вот в каком пространстве имёт тоже не нашёл)
Также не нашёл описания указанных классов

Так же интересует логика работы при выполнении указанных методов, а именно при выполнении методов .ScheduleMinutelyProcessJob() или .ScheduleJob() происходит ли первичный запуск нужного БП или только добавляется в расписание?

Добрый день!

1. В простанство имен Usings следует добавить:
- Quartz.Impl
- Quartz
- Quartz.Impl.Triggers
- Terrasoft.Core.Scheduler
2. При выполнении методов БП добавляется в расписание.

Здравствуйте.
Т.е. немедленного запуска перед добавлением в расписание не происходит?

При каких условиях при выполнении метода ScheduleMinutelyProcessJob() задача добавляется в таблицу QRTZ_FIRED_TRIGGERS? т.е. происходит немедленный запуск(описание проблемы в топике)?

Добрый день!

Необходимо запустить Ваш процесс (может быть запущен вручную или по событию). БП доходит до элемента “Задание сценарий”. Добавляется job в планировщик. В результате процесс будет запущен в следующий раз согласно указанного времени в параметре startOffset.

Здравствуйте. А что делать если выдает такую ошибку?

Добрый день. Добавляю назначенное задание по аналогии с примером выше:

UserConnection userConnection =  Get<UserConnection>("UserConnection");
//:запуск через 24 часа
//Добавляем в назначенное задание
 
string processName = "ProcessName";
string jobName = processName + "Job";
string jobGroupName = jobName + "Group";
 
int startOffset = 86400; //  (одни сутки)
AppScheduler.RemoveJob(jobName, jobGroupName);
var job = AppScheduler.CreateProcessJob(jobName, jobGroupName, processName, userConnection.Workspace.Name, "Supervisor");
var trigger = new SimpleTriggerImpl(jobName + "Trigger", jobGroupName, DateTime.UtcNow.AddSeconds(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);
 
return true;

Job появляется в [QRTZ_TRIGGERS], но поле TRIGGER_STATE = BLOCKED.
и в указанное время БП не запускается.
Идентичный код в другом БП добавляет job с TRIGGER_STATE = WAITING и БП прекрасно запускается.

Чем вызвана установка TRIGGER_STATE = BLOCKED?

Выявлено, что назначенное задание не отрабатывает только, когда пользователь авторизован в системе. Но как только он выходит, назначенное задание сразу отрабатывает.
А когда пользователь не авторизован, то невозможно использовать UserConnection, что необходимо для получения значения системных настроек и выполнения ESQ-запросов.
С чем связано такое поведение? и как решить проблему с UserConnection?

Версия 7.8.1681

"Коновалов Игорь" написал:

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

А когда пользователь не авторизован, то невозможно использовать UserConnection, что необходимо для получения значения системных настроек и выполнения ESQ-запросов.

С чем связано такое поведение? и как решить проблему с UserConnection?

Версия 7.8.1681


На дворе май 2017-го, но обозначенная Игорем проблема актуальна и для версии 7.10, т.е. процесс запускается планировщиком только после выхода пользователя из системы. Есть ли workaround?

"Давыдов Андрей Дмитриевич" написал:
Коновалов Игорь пишет:

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

А когда пользователь не авторизован, то невозможно использовать UserConnection, что необходимо для получения значения системных настроек и выполнения ESQ-запросов.

С чем связано такое поведение? и как решить проблему с UserConnection?

Версия 7.8.1681

На дворе май 2017-го, но обозначенная Игорем проблема актуальна и для версии 7.10, т.е. процесс запускается планировщиком только после выхода пользователя из системы. Есть ли workaround?


Опытным путем выяснил, что планировщик сбоит при отладке процесса w3wp в VisualStudio. Если отладчик не подключать, то планировщик работает нормально.

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

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

Предоставляю упрощённый пример моего кода:

define("SxAssignmentPreconfiguredPageV2", ["CustomProcessPageV2Utilities"],
    function() {
        return {
            messages: {},
            mixins: {
                BaseProcessViewModel: "Terrasoft.CustomProcessPageV2Utilities"
            },
            attributes: {
                "IsAssignment": {
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    dataValueType: Terrasoft.DataValueType.BOOLEAN,
                    caption: { bindTo: "Resources.Strings.IsAssignmentCaption" }
                },
               "OwnersString": {
                   type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                   dataValueType: Terrasoft.DataValueType.String,
                   dependencies: [{
                       columns: ["IsAssignment"],
                       methodName: "onIsAssignmentChanged"
                   }]
               }

            },
            methods: {
                onIsAssignmentChanged: function(){
                    debugger;
                  if(this.get("IsAssignment"))
                      this.set("OwnersString", "Поле заполнено");
                },
                                        /**
                                 * @overridden
                                 * @returns {string}
                                 */
                                getHeader: function() {
                                        return "PreconfiguredPageV2";
                                },
                                /**
                                 * @overridden
                                 */
                                onEntityInitialized: function() {
                                        this.callParent();
                                },
                                /**
                                 * @overridden
                                 */
                                initHeaderCaption: Ext.emptyFn,
                                /**
                                 * @protected
                                 * @overridden
                                 */
                                initPrintButtonMenu: Ext.emptyFn,
                                /**
                                 * @overridden
                                 * @param {Object} args Параметры
                                 * @param {Object} tag Тег
                                 */
                                loadVocabulary: function(args, tag) {
                                        args.schemaName = this.model.attributes[tag].referenceSchemaName;
                                        this.callParent(arguments);
                                },
                                /**
                                 * @overridden
                                 */
                                onCloseCardButtonClick: function() {
                                        this.sandbox.publish("BackHistoryState");
                                },
                                /**
                                 * @protected
                                 */
                                onNextButtonClick: function() {
                                        this.acceptProcessElement("NextButton");
                                }
            },
            diff:[
                {
                    "operation": "remove",
                    "name": "CloseButton"
                },
                {
                    "operation": "remove",
                    "name": "actions"
                },
                {
                    "operation": "remove",
                    "name": "SaveButton"
                },
                {
                    "operation": "remove",
                    "name": "DelayExecutionButton"
                },
                {
                    "operation": "remove",
                    "name": "ViewOptionsButton"
                },
                {
                    "operation": "insert",
                    "parentName": "Header",
                    "propertyName": "items",
                    "name": "HeaderLabel",
                    "values": {
                        layout: {column: 0, row: 0, colSpan: 12},
                        "itemType": Terrasoft.ViewItemType.LABEL,
                        "caption": { "bindTo": "Resources.Strings.HeaderLabelCaption" },
                        "labelClass": ["new-record-header-caption-label"]

                        /*"classes": {
                            "labelClass": [
                                "t-label "
                            ],
                            "wrapClass": [
                                "label-wrap"
                            ]
                        }*/

                    }
                },
                {
                    // Метаданные для добавления кнопки [Следующий]
                    "operation": "insert",
                    "parentName": "LeftContainer",
                    "propertyName": "items",
                    "name": "NextButton",
                    "values": {
                        caption: {bindTo: "Resources.Strings.NextButtonCaption"},
                        itemType: Terrasoft.ViewItemType.BUTTON,
                        classes: {textClass: "actions-button-margin-right"},
                        style: Terrasoft.controls.ButtonEnums.style.GREEN,
                        click: {bindTo: "onNextButtonClick"}
                    }
                },
                {
                    "operation": "insert",
                    "name": "IsAssignment",
                    "parentName": "Header",
                    "propertyName": "items",
                    "values":{
                        bindTo: "IsAssignment",
                        caption : {bindTo: "Resources.Strings.IsAssignmentCaption"},
                        layout: {column: 0, row: 1, colSpan: 6}
                    },
                    "index": 0
                },
                {
                    "operation": "insert",
                    "name": "OwnersString",
                    "parentName": "Header",
                    "propertyName": "items",
                    "values":{
                        bindTo: "OwnersString",
                        caption :  {
                            "bindTo": "Resources.Strings.OwnersStringCaption"
                        },
                        layout: {column: 0, row: 2, colSpan: 6},
                        "contentType": 0,
                        "controlConfig": {
                            "className": "Terrasoft.TextEdit"
                        }
                    }
                }


            ]
        };
    });

Заранее спасибо.

Нравится

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

Ошибка в типе атрибута, у системного перечисления DataValueType нет значения "String", но есть значение TEXT.

Спасибо, помогло.

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

Добрый день,
Используя стандартный элемент БП "Страница редактирования" открываю страницу редактирования, создаю новую запись, указываю ей данные, проблема в следующем при создании состояние указываю из справочника "Не начата", но если пользователь при переходе на данный элемент изменяет какие нибудь другие поля и нажимает "Сохранить" активности автоматически присваивается состояние "Завершена", как это изменить?
По БП пользователь должен только ознакомится с данными и при необходимости их поправить, но состояние должно остаться "Не начата", т.к. это активность на следующий день

Нравится

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

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

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

Для решения Вашей задачи Вы также можете использовать следующую последовательность элементов:
1) Страница редактирования.
2) Изменить данные (меняем состояние задачи на "Не начата").
3) Промежуточный обрабатывающий сигнал - ожидаем изменение состояния активности на конечное.

Второе решение - использовать элемент "Задача".

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

Добрый день,
Использую стандартный элемент БП Чтение данных, нужно выбрать звонки из Активностей, в которых начало меньше или равно текущей дате/времени, ставлю такое условие, но вытягиваются звонки у которых значение больше текущей даты/времени. Собственно вопрос в чем проблема, стандартный элемент не умеет сравнивать DateTime?
Причем дату сравнивает нормально, а вот по времени сравнение не идет.
1

Нравится

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

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

Элемент "Читать данные" умеет это делать. Проблема в другом:biggrin:

Поле "Ответственный" смотрит в [dbo].[Contact]. Значение "Текущий пользователь" берется из [dbo].[SysAdminUnit]. Поле "Ответственный" необходимо сравнивать со значением "Контакт текущего пользователя".

С этим фильтром хоть какие-то активности подтягиваются?

Как ни странно но подтягиваются по контакту текущего пользователя, так что с этим проблем нет, проблема только с датой

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

Правильно ли я понимаю, что "Текущее значение даты времени" - это параметр процесса? Каким значением заполняется этот параметр?

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

Добрый день.
Стоит задача отобразить в разделе Планирование:
- продукты в разрезе контрагентов
и
- Контрагентов в разрезе Ответственных.
Вопрос:
Как можно создать подобную иерархическую структуру в разделе Планирование с расчётом итоговых показателей по каждому родителю?

Версия Бандл SalesOmnichannal+MarketingCampaign 7.5.0.1422

Нравится

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

Добрый день, Игорь!

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

"Адасюк Валерий Викторович" написал:Дело в том, что иерархическая структура там уже реализована, но логику нужно реализовывать самостоятельно. Необходимо соответствующим образом заполнить родительские поля для элементов планирования.

А можно хотя бы направление, в котором двигаться?

Требуется реализовать возможность добавления подчинённых элементов средствами системы и полноценной работы с ними, а также автоматический пересчёт родительских элементов при изменении дочерних. Ввиду этого, как минимум, рекомендую начать работу с добавления записей и вычисления их Id дочерных/подчиненных элементов. В целом же вся реализация достаточно объемна и выполняется исключительно написанием скриптов.

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

Есть деталь "Регион проведения мероприятия" с полями "Страна" и "Регион". На странице детали так же есть еще одна деталь "Города". Стоит задача выводит в реестр детали страну, регион и список городов. Подскажите, как лучше реализовать данный функционал?

Нравится

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

Здравствуйте, Олег!

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

На самом деле особой надобности выводить список городов нет. Только в целях удобства. Можно поподробнее про вывод агрегируемой ф-ей? Или может эта тема есть в SDK? А там уже видно будет - стоит задачу решать, или оставить стандартный функционал.

Олег,
Агрегирующие функции производят вычисление одного «собирающего» значения (суммы, среднего, максимального, минимального значения и т. п.) для заданных групп строк таблицы.
То есть, вывести значения по городам невозможно, возможно лишь посчитать кол-во городов.

http://academy.terrasoft.ru/documents/docs/product/bpm'online%20real%20estate/real%20estate/7.6.0/BPMonlineHelp/chapter_list_setting/chapter_list_setting_columns.htm

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

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

Uncaught Terrasoft.UnsupportedTypeException: Message getCardInfo cannot be subscribed in undefined, message direction set as publish

В чем может быть проблема?

P.S. проблема появилась после обновления билда с 627 на 1422, до этого все работало нормально

Нравится

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

Здравствуйте, Олег!

Рекомендую Вам зарегистрировать обращение, написав на ящик support@terrasoft.ru

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

Добрый день.
В процессе разработки на бандле Sales+Marketing выявлена такая ошибка:
При замещении схемы "EventTargetPageV2", перестаёт работать кнопка "Сохранить".
Проблема оказалась в строке

this.superclass.save.apply(this, initialArgs);

в методе save родительской схемы.
Дело в том, что при наличии замещаемых схем метод this.superclass.save переопределяется и ссылается на на самого себя, что приводит к рекурсии.
Исправил переопределением метода save в замещающей клиентской схеме и заменой строки
this.superclass.save.apply(this, initialArgs);

на
this.superclass.superclass.save.apply(this, initialArgs);

Может есть другой (более правильный) вариант решения этой проблемы? Буду признателен за предложения.

Нравится

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

Добрый день, Игорь.

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

"E.Podkovka" написал:Вообще, правильным решением является использование callParent.

callParent не помог.

"Коновалов Игорь" написал:

callParent не помог.

Тогда используйте superclass.superclass.

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