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

Версия 7.8 sales.

Есть стандартная деталь с реестром, добавлена на странице, вот такая, например: https://academy.terrasoft.ru/documents/technic-sdk/7-8/sozdanie-detali-s...

Возможно уже обсуждалось, не нашёл - можно ли для некоторых колонок задать свой цвет?

Нравится

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

Денис, здесь есть некоторая информация - http://www.community.terrasoft.ru/forum/topic/12359
А так просто не получиться, для всей записи в гриде детали –пожалуйста. А для конкретных колонок по умолчанию такого не предусмотрено, только с помощью «магии».
Например, можно написать CSS стиль на какую-то по счету колонку в реестре и запретить редактировать настройку колонок этой детали.

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

Здраствуйте
У меня есть деталь. Можно как то добавлять динамически колонки в деталь(чтобы эти колонки не были привязаные к таблице самой детали)?

Нравится

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

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

Для реализации данного функционала Вам необходимо смотреть в сторону замещения метода loadGridData из схемы GridUtilitiesV2 (или одного из вызываемых в нем методов). В данном методе и происходит подгрузка данных в деталь на основании фильтров, настроек детали и отображаемых колонок.

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

"Владимир Соколов" написал:

А можно подсказать, где реализована похожая функциональность?

Чтобы создать динамическую таблицу, где, например, строки - это оборот, колонки - это валюты, а в ячейках отображаются некоторые %, которые соответствуют обороту и валюте.

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

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

Здравствуйте.
У меня такой вопрос: можно ли сделать кастомную страницу для отображения данных таблицы в виде реестра? Я попробовал использовать преднастроенную страницу в БП, но ничего у меня не вышло.

Нравится

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

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

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

Виталий, опишите, пожалуйста, бизнес-задачу.

Так как по описанию не совсем понятно, что вы пытаетесь реализовать.


Здравствуйте. У меня в БП по определенным параметрам делается поиск контрагентов и результат заносится в новый объект. И вот, после поиска нужно отобразить этот результат в виде реестра (только отобразить, т.е. с этими данными ничего сделать нельзя).

Прилагаю также скриншот БП:

В пробовал работать с элементом "Преднастроенная страница 1", но ничего не вышло.

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

Для решения данной задачи вам стоит смотреть в сторону использования контрола Terrasoft.Grid. Пример его добавления и использования есть в схеме BaseSectionV2 (NUI), эелемент DataGrid (он и отвечает за реестр записей в разделе). Особое внимание обратите на миксин GridUtilitiesV2, т.к. он содержит основные методы для работы с данным контролом.

Так же, как вариант, вы можете динамически генерировать разметку основываясь на коллекции данных используя HTML тэги и ExtJs.

Так же обратите внимание, что базовая Пред настроенная страница не наследует ту же иерархию что и схемы редактирования карточек.

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

Здравствуйте, коллеги.

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

Кейс такой:
Есть отрендеренный контейнер через  Ext.create("Terrasoft.Container", _viewConfig) . Как в отрендеренный контейнер добавить еще контейнеры?

Нравится

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

Код вот такой.

createBody: function() {
      createBody: function() {
      var _model = {
       values: {},
       columns: {},
       methods: {
 
        init: function() {
         this.set("_id", Terrasoft.generateGUID());
         this.set("_items", []);
         this.set("_rows", new Terrasoft.Collection());
         this.setRendered(false);
        },
 
        setConfig: function(config) {
         this.set("_config", config || []);
        },
 
        getConfig: function() {
         return (this.get("_config"));
        },
 
        setRendered: function(f) {
         this.set("_isRendered", f);
        },
 
        isRendered: function() {
         return (this.get("_isRendered"));
        },
 
        getId: function() {
         return (this.get("_id"));
        },
 
        /**
         * @returns {Terrasoft.Collection}
         */
        getRowConfig: function() {
         var _items = new Terrasoft.Collection(),
          _config = this.getConfig();
         _config.forEach(function(confItem) {
          var _item = {
           name: confItem.name,
           dataValueType: confItem.dataValueType,
           caption: (Terrasoft.isUndefined(confItem.caption) ? "[N/D]" : confItem.caption),
           isRequired: (Terrasoft.isUndefined(confItem.isRequired) ? false : confItem.isRequired),
           visible: (Terrasoft.isUndefined(confItem.visible) ? true : confItem.visible)
          };
          if (confItem.hasOwnProperty("isLookup")) {
           _item.isLookup =  confItem.isLookup;
          }
          if (confItem.hasOwnProperty("referenceSchema")) {
           _item.referenceSchema =  confItem.referenceSchema;
          }
          if (confItem.hasOwnProperty("defaultValue")) {
           _item.defaultValue =  confItem.defaultValue;
          }
          _items.add(confItem.name, _item);
         });
         return (_items);
        },
 
        /**
         *
         * @returns {Terrasoft.Collection}
         */
        getRows: function() {
         return (this.get("_rows"));
        },
 
        getRowsViews: function() {
         var _items = [];
         this.getRows().each(function(row) {
          if (!row.isRendered()) {
           row.render();
          }
          _items.push(row.getView());
         });
         return (_items);
        },
 
        getView: function() {
         return (this.get("_container"));
        },
 
        getViewConfig2: function() {
         var _config = this.getViewConfig();
         _config.items = this.getRowsViews();
         return(_config);
 
        },
 
        getViewConfig: function() {
         var _id = "TableBody_" + this.getId();
         return ({
          id: _id,
          selectors: { wrapEl: "#" + _id },
          classes: {wrapClassName: ["im-table-body"]},
          items: this.get("_items")
         });
        },
 
        render: function() {
         var _container = null;
         if (!this.isRendered()) {
          this.set("_items", this.getRowsViews());
          var _viewConfig = this.getViewConfig();
          _container = Ext.create("Terrasoft.Container", _viewConfig);
          this.setRendered(true);
         }
         this.set("_container", _container);
        },
 
        reRender: function() {
         if (this.isRendered()) {
          this.set("_items", this.getRowsViews());
          this.getView().reRender();
         }
        },
 
        createRow: function() {
         var _config = this.getRowConfig().getItems();
         var _model = {
          values: {},
          columns: {},
          methods: {
 
           init: function(id) {
            id = id || Terrasoft.generateGUID();
            this.set("_id", id);
            this.set("_items", []);
            this.setConfig(_config);
            this.setEditMode(false);
            this.setRendered(false);
           },
 
           getId: function() {
            return (this.get("_id"));
           },
 
           setConfig: function(config) {
            this.set("_config", config);
           },
 
           getConfig: function() {
            return (this.get("_config"));
           },
 
           setEditMode: function(f) {
            this.set("_isEditMode", f);
           },
 
           isEditMode: function() {
            return (this.get("_isEditMode"));
           },
 
           setRendered: function(f) {
            this.set("_isRendered", f);
           },
 
           isRendered: function() {
            return (this.get("_isRendered"));
           },
 
           getData: function() {
 
           },
 
           getView: function() {
            return (this.get("_container"));
           },
 
           getViewConfig: function() {
            var _id = "TableRow_" + this.getId();
            return ({
             id: _id,
             selectors: { wrapEl: "#" + _id },
             classes: {wrapClassName: ["im-table-header"]},
             items: this.get("_items")
            });
           },
 
           getColumnModel: function(config) {
            var itemDataValueType = config.dataValueType;
            var itemName = config.name;
            var itemId = "Row" + this.getId() + "_" + itemName;
            var controlConfig = {};
            switch (itemDataValueType) {
             case Terrasoft.DataValueType.TEXT:
              controlConfig = {
               id: itemId + "Label",
               className: "Terrasoft.Label",
               caption: {bidTo: itemName},
               isRequired: config.isRequired
              };
              break;
            }
            return controlConfig;
           },
 
           getRowConfig: function() {
            var _config = this.getConfig(),
             _items = new Terrasoft.Collection();
            _config.forEach(function(confItem) {
             _items.add(this.getColumnModel(confItem));
            }, this);
            return (_items);
           },
 
           render: function() {
            var _container = null;
            if (!this.isRendered()) {
             this.set("_items", this.getRowConfig().getItems());
             var _viewConfig = this.getViewConfig();
             _container = Ext.create("Terrasoft.Container", _viewConfig);
             this.setRendered(true);
            }
            this.set("_container", _container);
           },
 
           reRender: function() {
            if (this.isRendered()) {
             this.set("_items", this.getRowConfig().getItems());
             this.getView().reRender();
            }
           }
          }
         };
 
         _config.forEach(function(confItem) {
          var _name = confItem.name,
           _column = {
            dataValueType: confItem.dataValueType,
            caption: confItem.caption,
            isRequired: confItem.isRequired,
            type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
           },
           _value = confItem.defaultValue || null;
          if (confItem.dataValueType === Terrasoft.DataValueType.LOOKUP) {
           _column.isLookup = confItem.isLookup || false;
           _column.referenceSchemaName = confItem.referenceSchemaName;
           _model.values[_name + "List"] = new Terrasoft.Collection();
          }
          _model.values[_name] = _value;
          _model.columns[_name] = _column;
         });
         var _rowViewModel = Ext.create("Terrasoft.BaseViewModel", _model);
         _rowViewModel.Ext = Ext;
         _rowViewModel.sandbox = sandbox;
         _rowViewModel.Terrasoft = Terrasoft;
         return _rowViewModel;
        },
 
        addRow: function(collection) {
         if (collection.getCount() > 0) {
          var _id = Terrasoft.generateGUID(),
           _row = this.createRow();
          _row.init(_id);
          _row.set("Id", _id);
          collection.eachKey(function(key, val) {
           _row.set(key, val);
          });
          this.getRows().add(_row);
          this.reRender();
         }
        }
       }
      };
 
      var _bodyViewModel = Ext.create("Terrasoft.BaseViewModel", _model);
      _bodyViewModel.Ext = Ext;
      _bodyViewModel.sandbox = sandbox;
      _bodyViewModel.Terrasoft = Terrasoft;
      return _bodyViewModel;
     }

Здравствуйте.
Какая версия приложения?

Извините, Илья, что так долго.
1. версия 7.7
2. "разрулил" вопрос через JQuery

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

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

Версия 7.8 sales.

Вопросы такие - в некоторый объект можно импортировать данные через Excel файл. Допустим, в нашем случае на странице Продаже создана деталь "Коммерческое предложение в продаже", с некоторыми колонками. В числе колонок есть и привязка к конкретной продаже (колонка типа справочник - см. скрин).

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

2. Начиная с какой версии идёт поддержка Excel? Допустим, файл сделанный в 2003 будет ли работать?

Нравится

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

1. В «продаже» есть первичное поле для отображения, в нём указан её номер или код. Вот его и можно указать в Excel-файле с данными с детали как поле для привязки к продаже.
2. Работает только с xlsx-файлами. 2003 так сохранять не умеет.

"Зверев Александр" написал:1. В «продаже» есть первичное поле для отображения, в нём указан её номер или код. Вот его и можно указать в Excel-файле с данными с детали как поле для привязки к продаже.

Первичное поле - это колонка id, как я понимаю? Т.е. в Excel файле нужно будет создать специальную колонку, где будет указан id продажи, вида 1a860305-e9c3-4f28-a4d6-05a07828f9fa ?

Нет, в любом разделе есть первичное поле для отображения. Для контакта это ФИО, для контрагента — название.

Александр, но ведь по идее могут быть разные продажи с одинаковым названием, так же как и контакты с одинаковым ФИО и т.д.

Уникальным ведь является только id.

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

Фактически система сравнивает значение из файла Excel со значением первичного для отображения поля объекта. Для объекта "продажа" по умолчанию первичное для отображения поле - "Название".

Для решения необходимо:
1) Создать поле с типом "Строка 50 символов"
2) Реализовать логику, которая будет переносить значение поля Id в созданное поле для новых записей, а также реализовать перенос для существующих записей
3) В расширенных свойствах объекта "Продажа" изменить первичное для отображения поле
4) Импортировать записи

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

Дорый день!

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

Нравится

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

Есть такой пример:


Добавление правила поиска Контрагентов по названию
Пользовательскими средствами реализовать невозможно. Однако, разработчик может создать свои правила поиска дублей по аналогии с тем, как реализованы стандартные правила на уровне базы данных (найти их можно в хранимых процедурах FindAccountDuplicate(для контрагента) и FindContactDuplicate(для контакта)).

Добавить запись в таблицу DuplicateRule:

INSERT INTO DuplicatesRule
 
(Name,
 
IsActive,
 
ObjectId)
 
VALUES
 
('Account duplicates. Account name',
 
'1',
 
'25D7C1AB-1DE0-4501-B402-02E0E5A72D6E')

1

2. Изменить хранимую процедуру tsp_FindAccountDuplicate (если правило поиска дублей для контакта, то менять tsp_FindContactDuplicate)(во вложении находится пример измененной хранимой процедуры tsp_FindAccountDuplicate):
Объявить правило AccountName, указать Id с таблици DuplicatesRule:
2

Добавить описание работы правила AccountName:
3

"Зверев Александр" написал:

Есть такой пример:

Цитата:

Добавление правила поиска Контрагентов по названию

Пользовательскими средствами реализовать невозможно. Однако, разработчик может создать свои правила поиска дублей по аналогии с тем, как реализованы стандартные правила на уровне базы данных (найти их можно в хранимых процедурах FindAccountDuplicate(для контрагента) и FindContactDuplicate(для контакта)).

Добавить запись в таблицу DuplicateRule:

INSERT INTO DuplicatesRule



(Name,



IsActive,



ObjectId)



VALUES



('Account duplicates. Account name',



'1',



'25D7C1AB-1DE0-4501-B402-02E0E5A72D6E')

1

2. Изменить хранимую процедуру tsp_FindAccountDuplicate (если правило поиска дублей для контакта, то менять tsp_FindContactDuplicate)(во вложении находится пример измененной хранимой процедуры tsp_FindAccountDuplicate):

Объявить правило AccountName, указать Id с таблици DuplicatesRule:

2

Добавить описание работы правила AccountName:

3

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

1.png
32.16 кб

2.png
46.68 кб

3.png
135.54 кб

tsp_findaccountduplicate.zip
2.45 кб


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

Это 2 разных механизма, глобальный и локальный поиск. Эти правила — только для глобального. А для локального:


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

•При сохранении нового контрагента — по полям [Название], [Альтернативное название] и детали [Средства связи].
•При сохранении нового контакта — по полям [ФИО], [Мобильный телефон], [Домашний телефон], [Skype], [Email].

"Зверев Александр" написал:

Это 2 разных механизма, глобальный и локальный поиск. Эти правила — только для глобального. А для локального:

Цитата:

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

•При сохранении нового контрагента — по полям [Название], [Альтернативное название] и детали [Средства связи].

•При сохранении нового контакта — по полям [ФИО], [Мобильный телефон], [Домашний телефон], [Skype], [Email].

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

Возможно, нужно дорабатывать хранимку tsp_SearchForAccountDuplicates (список параметров очень похож на цитату выше). Но не факт, надо смотреть, где она вызывается в конфигурации.

Здравствуйте! Я на 3.x делаю доработки по дублям, процедуру я поменяла, в верхней таблице списка дубликатов сам список дублей хорошо отображается, изменила отображение деталей (фильтры не по равенству, а на включение (содержит ..)). Единственное что не получается - пересчитать количество дублей в верхней таблице. Буду благодарна советам ) спасибо!

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

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

Это окно в конфигурации называется wnd_ViewSearchResult.

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

Светлана, в этой теме обсуждается работа с дублями в 7.Х, она полностью отличается от того, что было в 3.4. Попробуйте задать свой вопрос в нужной ветке, подробно описав со скриншотами и листингами, где и что Вы меняете, что хотите получить, как работает сейчас и что в этом не устраивает.

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

В БП в элементе "Страница редактирования" в блоке "считать элемент выполненным" стоят условия - поле с датой не равно этому же полю из элемента "Читать данные" в начале БП. По сути условие - должна быть изменена дата. При сохранении карточки в журнале выдает ошибку "Неправильный синтаксис около конструкции ">"". Если извлечь из элемента текст запроса, то после ">" ничего нет. При сравнении даты с параметром - тоже самое.

Нравится

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

В версии 7.8.0 такого нет.

Возможно у чтения данных не установлен признак "Сериализовать в БД"

Признак "Сериализовать в БД" установлен.

Версия какая? Нами выявлены множественные ошибки при работе с параметрами в БП 7.8.2. Решение вырубить проверку корректности заполнения поля. Наибольшие проблемы с элементом "Читать данные". Проявляется, если используется несколько полей из "Читать данные" в рамках одного элемента БП. Есть скрипт, который надо пустить в консоли браузера. Побочный эффект - процесс станет обязательно компилируемым.

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

Доброго всем дня.

Версия 7.8 sales.

Задача следующая: есть данные по звонкам, в числе которых хранятся дата, кто кому звонил и т.д., ну и запись самого звонка в файле wav (хранится на стороннем сервере, в соответствующую колонку UsrLink записана только ссылка на этот файл).

Сделан свой небольшой контрол для проигрывания записи при помощи стандартного тега HTML audio.

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

А вот как сделать то же самое на списковой странице? Сейчас блок audio подставляется в схеме списковой CallSection следующим образом:

diff: /**SCHEMA_DIFF*/[
                        {
                                "operation": "insert",
                                "name": "UsrAudio",
                                "values": {
                                        "className": "Terrasoft.UsrAudioControl",
                                        "layout": {
                                                "colSpan": 12,
                                                "rowSpan": 1,
                                                "column": 0,
                                                "row": 0
                                        },
                                        "generator": "UsrAudioControlGenerator.generateUsrAudioControl",
                                        "visible": true,
                                        //"getAudioLink": "getAudioLink",
                                        "myParam": {"bindTo": "getAudioLink"},//"myParam" - собственно, в этот параметр должно быть записано значение UsrLink. Если я подставляю сюда произвольное значение - оно выводится. Как вытащить ссылку?
                                },
                                "parentName": "DataGrid",
                                "propertyName": "activeRowActions",
                                "index": 10
                        }
        ]/**SCHEMA_DIFF*/,

Также есть метод:

getAudioLink: function() {

                                return this.get("UsrLink");
                        },

Но он не работает.

Нравится

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

Функция this.get("UsrLink"); в контексте секции не вернет вам ваш линк из объекта, поставьте точку остановки на этом return вашего метода getAudioLink и посмотрите, что возвращает this.get("UsrLink"); и вместо этого используйте this.getActiveRow() который вернет модель всей текущей строки, в которой уже можно достать нужные вам данные.

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

Здраствуйте! Пробовал добавить кнопку в стадии в соответствии с документацией: https://academy.terrasoft.ru/documents/technic-sdk/7-8/dobavlenie-novogo...

Документация: Для замещающей клиентской схемы необходимо установить в качестве родительского объекта схему SectionActionsDashboard пакета ActionsDashboard. В качестве заголовка также можно указать значение SectionActionsDashboard.

При замещены данной схемы выбираю Родительский объект "BaseActionDashboard" пакета ActionDashboard. Согласно название модуля будет BaseActionsDashboard, а нужно что бы было SectionActionDashboard. При изменении названия модуля на SectionActionDashboard остается название BaseActionDashboard.

Подскажите пожалуйста что делаю не так.

Нравится

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

Добрый день, Дмитрий!
Вы пытаетесь какую схему заместить? В документации указанно, что родителем необходимо выбирать схему SectionActionsDashboard, Вы же выбираете BaseActionDashboard, соответственно система его и выбирает родителем.

Сохраните Ваш код, который Вы прописали в diff, перейдите в конфигурацию, нажмите добавить "Замещающий клиентский модуль" и сразу в поле родительский объект скопируйте название "SectionActionsDashboard". Как только Вы его выбирите, то все будет как надо.

Вот что должно получится:

Подскажите пожалуйста, как сделать свою картинку в формате svg. Которая отображалась корректно. Я добавил свою картинку формата svg, но она отображается только при наведении на нее (прикрепил рисунок).
Сылка на картинку:
http://www.flaticon.com/free-icon/right-arrow_137624#term=next&page=1&p…

Добрый день, Дмитрий!

Ссылка на инструкцию по созданию файла формата svg https://svgontheweb.com/ru/

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

Добрый день!
Вводная: Клиенту не удобно использовать деталь характеристика у Продукта. Хочет все поля заполнять в самой карточке. Характеристики разные в зависимости от типа продукта.
Простое решение: Добавить все поля-характеристики в карточку и скрывать в зависимости от типа.
Вопрос: Но хотелось бы сделать красиво. Есть ли возможность для BPMOnline 7.8 отображать поле и привязывать его к колонке объекта на этапе инициализации карточки редактирования? Ext.JS позволяет это сделать, но попытки реализовать по примерам для него к успеху не привели. Прошу помочь небольшим примером.

Нравится

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

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

Поля можно скрывать бизнес-правилами. Пример:
https://academy.terrasoft.ru/documents/technic-sdk/7-8/pravilo-bindpara…

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

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

Поля можно скрывать бизнес-правилами


Здравствуйте, Илья! Да, через бизнес-правила тоже можно. Но, и скрытие полей кодом, и через правила требует внесения изменений в код, каждый раз, при добавлении нового типа продукта. Необходимо сделать универсально. Т.е. динамически удалять/добавлять поля. А сами имена полей и зависимость от типа получать из справочника. При такой реализации, достаточно будет добавить запись в такой справочник, а код страницы редактирования останется прежним. Именно поэтому, нужен пример создания поля динамически.

Здравствуйте, Эмин.

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

Более простым, но не столь функциональным решением будет использовать стандартные свойства visible элементов и добавлять поля на карточку стандартными

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