Вопрос

Собственно, нужно получить некие данные с внешнего API, и потом нарисовать их на странице раздела. Прошу подсказки, в какую сторону смотреть и двигаться. В Академии есть пример с добавлением строки-приветствия. Однако, совсем не понятен принцип работы кода с примера. Документация по Terrasoft Javascript API так же не понятна. Прошу подсказки, куда смотреть и в какую сторону двигаться.

У меня такой же вопрос

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

Если сервер API предоставляет специализированные заголовки CORS то в Вашем распоряжении вся мощь JavaScript в клиентской схеме, делайте запросы (н/п используя инструментарий используемой библиотеки Ext.JS AJAX), обрабатывайте ответы - устанавливайте атрибуты для заполнения полей и т.д.

Если сервер API не предоставляет специализированные заголовки CORS то в данном случае Вам придется писать код C# (Здесь я сильно не подскажу что да как, веб-сервис что-то там такое есть)
После чего можете например по websocket протоколу пробросить события с данными в клиентские карточки (как это сделать обсуждалось вот здесь)

"Севостьянов Илья Сергеевич" написал:Если сервер API не предоставляет специализированные заголовки CORS то в данном случае Вам придется писать код C#

Из js вызываете сервис. В сервисе обычные post/get запросы с помощь System.Web. Получаете ответ от сервера, делаете return, в js-коллбеке проходит ответ в json-строке. Сериализуете, обрабатываете далее как угодно

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

Добрый день!
Задача такая - в разделе Заказы есть деталь Площадка - объект, куда необходимо доставить продукт. Площадок в заказе может быть несколько. Необходимо отобразить на карте объекты в выбранных заказах.

На странице OrderSectionV2 добавила кнопку "Показать площадку на карте", при этом в В define и function прописала "MapsUtilities", "MapsHelper".
Добавила функцию:

openShowOnMap: function() {
                                var items = this.getSelectedItems();//отмеченные галкой заказы - массив
                                var Farm = [];//массив площадок
                                var select = Ext.create("Terrasoft.EntitySchemaQuery", {
                                        rootSchemaName: "UsrPlatform1C"
                                });
                                select.addColumn("UsrPlatform");
                                select.addColumn("UsrOrder");
                                select.filters.add("UsrPlatformId", this.Terrasoft.createColumnInFilterWithParameters("UsrOrder", items));
                                select.getEntityCollection(function(result) {
                                        if (result.success) {
                                                Terrasoft.each(result.collection.getItems(), function(item) {
                                                        Farm.push(item.set("UsrPlatform").value);
                                                });
                                        }
                                });
                                var selectS = Ext.create("Terrasoft.EntitySchemaQuery", {
                                        rootSchemaName: "UsrFarm"
                                });
                                selectS.addColumn("Id");
                                selectS.addColumn("UsrName");
                                selectS.addColumn("UsrAdress");
                                selectS.addColumn("UsrCity");
                                selectS.addColumn("UsrRegion");
                                selectS.addColumn("UsrCountry");
                                selectS.addColumn("UsrGPSN");
                                selectS.addColumn("UsrGPSE");
                                selectS.filters.add("FarmId", this.Terrasoft.createColumnInFilterWithParameters("Id", Farm));
                                selectS.getEntityCollection(function(result) {
                                        if (result.success) {
                                                var mapsConfig = {
                                                        mapsData: []
                                                };
                                                result.collection.each(function(item) {
                                                                var address = [];
                                                        if (item.get("UsrCountry") && item.get("UsrCountry").displayValue) {
                                                                address.push(item.get("UsrCountry").displayValue);
                                                        }
                                                        if (item.get("UsrRegion") && item.get("UsrRegion").displayValue) {
                                                                address.push(item.get("UsrRegion").displayValue);
                                                        }
                                                        if (item.get("UsrCity") && item.get("UsrCity").displayValue) {
                                                                address.push(item.get("UsrCity").displayValue);
                                                        }
                                                        address.push(item.get("UsrAdress"));
                                                        var dataItem = {
                                                                caption: item.get("UsrName"),
                                                                content: "

"

+ item.get("UsrName") + "
" + address.join(", ") + "
"
,
                                                                address: item.get("UsrAdress") ? address.join(", ") : null,
                                                                //конвертирование полей долготы и широты
                                                                gpsN: parseFloat(item.get("UsrGPSN")),
                                                                gpsE:  parseFloat(item.get("UsrGPSE")),
                                                                updateCoordinatesConfig: {
                                                                        schemaName: "UsrFarm",
                                                                        id: item.get("Id")
                                                                }
                                                        };
                                                        mapsConfig.mapsData.push(dataItem);
                                                });
                                                MapsUtilities.open({
                                                        scope: this,
                                                        mapsConfig: mapsConfig
                                                });
                                        }
                                }, this);
                        }

При отладке кода выяснила, что фильтрация по выбранным заказам выполняется, получаем выбранные заказы и площадки в этих заказах.
А в запросе при выборе Адреса, Региона, Страны получаем данные ВСЕХ площадок, которые есть в базе данных, а не только полученных из предыдущего запроса. (скриншот во вложении). Помогите, пожалуйста, разобраться в чем ошибка в фильтрации в запросе!!!

У меня такой же вопрос

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

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

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

И на момент добавления фильтра в строке:

selectS.filters.add("FarmId", this.Terrasoft.createColumnInFilterWithParameters("Id", Farm));

массив Farm пустой. Следовательно, фильтрация не отрабатывает. Рекомендую Вам смотреть в сторону использования метода Terrasoft.chain или же формировать второй запрос к базе данных в callback функции первого запроса, а если точнее то сразу после кода:

Terrasoft.each(result.collection.getItems(), function(item) {
            Farm.push(item.set("UsrPlatform").value);
        });

Илья, спасибо большое за Ваш ответ.

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

Добрый день!
Подскажите пожалуйста как добавить действие в карточку контакта, так чтоб оно не сыпало при вызове из combined mode и не было доступно в разделе?
Сейчас есть замещающая страница ContactPage и переопределен метод getActions, в который добавлено действие: actionMenuItems.addItem(this.getButtonMenuItem({
"Caption": { "bindTo": "Resources.Strings.UsrSetToSaleCaption" },
"Tag": { bindTo: "setToSaleProcess" }
}));
при вызове из карточки работает нормально, но из совмещенного режима падает с ошибкой, что метод не найден.
Версия 7.7.0.2293

У меня такой же вопрос

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

Здравствуйте!
Посмотрите здесь - http://www.community.terrasoft.ru/forum/topic/13848

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

Нужно показывать действие по условию.
Сделал действие в карточке:

                getActions: function() {
                    var actionMenuItems = this.callParent(arguments);
                    actionMenuItems.addItem(this.getButtonMenuItem({
                        "Caption": {"bindTo": "Resources.Strings.UsrFormContractCaption"},
                        "Tag": "FormContract",
                        "Visible": {"bindTo": "FormContractVisible"}
                    }));
                    return actionMenuItems;
                },
                FormContractVisible: function(){
                    var contract = this.get("UsrContract");
                    var state = this.get("Status")?this.get("Status").value:false;
                    if(!contract && state == Constants.OrderStatus.formation){
                        return true;
                    }else{
                        return false;
                    }
                }

При режиме карточки всё отрабатывает отлично.
Далее добавил действие в Section.

            getSectionActions: function(){
                var actionMenuItems = this.callParent(arguments);
                actionMenuItems.addItem(this.getButtonMenuItem({
                    "Caption": {"bindTo": "Resources.Strings.UsrFormContractCaption"},
                    "Tag": "FormContract",
                    "Visible": {"bindTo": "FormContractVisible"}
                }));
                return actionMenuItems;
            },
            FormContractVisible: function(){
                var activeRow = this.getActiveRow();
                if(!activeRow) return;
                var Contract = UsrContract || activeRow.values.UsrContract;
                var Status = Status || activeRow.values.Status.value;
                if(!Contract && Status == Constants.OrderStatus.formation){
                    return true;
                }else{
                    return false;
                }
            }

При режиме combined тоже всё стало отрабатывать. Но если в карточке изменить поле, например UsrContract то видимость уже не изменяется. Можно после сохранения карточки, например в функции onCardModuleResponse переинициализировать действия, но как это сделать не нашёл.
Подскажите как правильно реализовать задачу.

Версия 7.7

У меня такой же вопрос

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

Тут есть две проблемы:

1. В activeRow попадают только те колонки, что выведены на реестр. Следовательно и проверять в своей функции FormContractVisible вы можете только те колонки что видны вам в реестре(!). Иначе значения будут неопределенными, и результат проверки явно ошибочным;

2. Метод getSectionActions срабатывает только при смене фокуса между строками реестра, то есть, что бы ваши actionMenuItems увидели изменения в комбинированном режиме, вам нужно перейти от одной записи к другой и обратно, что, не очень то и удобно.

Что бы избежать первой проблемы, вам стоит из activeRow только гуид записи, а остальное вытягивать с помощью запросов ESQ.

Что бы по изменению значения на форме, секция об этих изменениях узнавала в реальном времени, без необходимости переключатся по записям.
Вам стоит использовать сообщения. (sandbox)
Поищите по конфигурации примеры использования, их очень много, ключевые слова: sandbox.subscribe и sandbox.publish

Алгоритм конечной реализации для комбинированного может быть приблизительно таким:

1. Видимость вашего actionMenu итема в секции, вы привязываете к атрибуту секции;
2. В секции, объявляете сообщение, в методе init подписываетесь на него через sandbox.subscribe;
2a. Обработчик этого сообщения меняет атрибут, к которому привязана видимость экшена.
3. В карточке по событию изменения целевых полей, вы генерируете адресное сообщение через sandbox.publish

Все, меняется карточка, про это узнает секция, меняется атрибут, меняется видимость экшена.
Если возникнут точечные вопросы во время реализации, пишите, постараемся ответить.

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

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

Да. Надо было всего-лишь в секшене видимость подвязать на атрибут.
Как-то я протупил) Спасибо за наводочку)

"Щиголь Максим" написал:Алгоритм конечной реализации для комбинированного может быть приблизительно таким:

1. Видимость вашего actionMenu итема в секции, вы привязываете к атрибуту секции;
2. В секции, объявляете сообщение, в методе init подписываетесь на него через sandbox.subscribe;
2a. Обработчик этого сообщения меняет атрибут, к которому привязана видимость экшена.
3. В карточке по событию изменения целевых полей, вы генерируете адресное сообщение через sandbox.publish

и такое workaround планируется считать нормальным решением?

"Владимир Соколов" написал:и такое workaround планируется считать нормальным решением?

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

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

Создал для контрагента действие:

              getActions: function() {
                  var actionMenuItems = this.callParent(arguments);
                  actionMenuItems.addItem(this.getActionsMenuItem({
                      "Caption": { "bindTo": "Resources.Strings.SxActionOpportunity" },
                      "Enabled":  { bindTo: "isClient" },
                      methodName: "runOpportunityManagement"
                  }));
                  return actionMenuItems;
              },

Действие должно быть активно только для контрагента с типом Клиент или Потенциальный клиент. Написал метод:

              isClient: function() {
                  var type = this.get("Type");
                  if(type) {
                      type = type.value;
                  }
                  if(type === Home32Constants.Account.Type.Client || type === Home32Constants.Account.Type.PotencialClient){
                      return true;
                  }else{
                      return false;
                  }
              },

Функция возвращает "true" а действие всё-равно не активно. А вот если закрыть левую панель(там где список записей раздела) и обновить страничку - всё отрабатывает как нужно.

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

Вопрос с Caption решается добавлением Strings в Section раздела, а вот как быть с Enabled не понятно.

У меня такой же вопрос

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

Добрый день, Вячеслав!

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

В версии 7,4 удалось решить проблему таким образом:

              initCardActionHandler: function() {
                  this.callParent(arguments);
                  var propertyNames = [
                      "isClient"
                  ];
                  this.Terrasoft.each(propertyNames, function(propertyName) {
                      this.on("change:" + propertyName, function(model, value) {
                          this.sandbox.publish("CardChanged", {
                              key: propertyName,
                              value: value
                          }, [this.sandbox.id]);
                      }, this);
                  }, this);
              },

В следующем проекте уже на версии 7.5 стоит похожая задача, но данное решение уже не помогает.

В версии 7.5 такое решение тоже будет работать если isClient будет свойством, а не функцией. Для того, чтоб все работало, нужно в Карточке сделать isClient и уже к нему байндить "Enabled" действия.

Да. Действительно если биндиться на свойство всё отрабатывает. Спасибо!

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

Добрый день!
Добавила действие в раздел, при нажатии на действие должен происходить запуск процесса, но не происходит. С чем это может быть связано?

Реализация - в прикрепленном в файле

У меня такой же вопрос

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

Используемый метод showGrafInfo должен выглядеть следующим образом:

showGrafInfo: function() {
var processArgs = {
sysProcessName: "ProcessGrafShip",
parameters: {
}
};
ProcessModuleUtilities.executeProcess (processArgs);
},

Спасибо, получилось

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

Здравствуйте!
Помогите, пожалуйста, добавить кнопку в список "Действие" в карточке контрагента

У меня такой же вопрос

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

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

structure.userCode = function() {
...
	this.actions.push({
		caption: resources.localizableStrings.ActionCaption,
		methodName: 'actionMethod'
	});
	this.methods.actionMethod = function() {
		alert('test');
	};
...
};

"Андрей Каспаревич" написал:

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

structure.userCode = function() {
...
        this.actions.push({
                caption: resources.localizableStrings.ActionCaption,
                methodName: 'actionMethod'
        });
        this.methods.actionMethod = function() {
                alert('test');
        };
...
};

С уважением,
Каспаревич Андрей
Эксперт 3-й линии поддержки


Спасибо. Извините за неверную формулировку вопроса.
В карточку контакта добавить действие удалось и все работает
Но в карточке контрагента получаю вот такую ошибку

Uncaught TypeError: Cannot read property 'push' of undefined 

Разобрался. Для карточки контрагента необходимо сначала создать переменную-массив, а затем приравнять ее к this.actions

var myActions = [];
myActions.push({
 caption: resources.localizableStrings.Name,
 methodName: 'Method'
});
this.actions = myActions;

Еще раз спасибо за помощь!

Эмин, рад, что Вы разобрались! Я как раз забыл это упомянуть.

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

подскажите пожалуйста, как создать на нужной детали, новое "Действие"?

У меня такой же вопрос

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

В нужном вам гриде детали во вкладке не визуальные, создайте новый Action, в конфигурации можете глянуть примеры, начинаются вкладки действий в не визуальных со слова "ami"

создал, но действие в контекстном меню не появилось

Здравствуйте, Тимофей! Вами используется коробочная деталь или созданная Вами?

От какого окна она наследуется? Производился ли перезапуск/очистка кэша приложения?

"Alimova Anna" написал:

Здравствуйте, Тимофей! Вами используется коробочная деталь или созданная Вами?

От какого окна она наследуется? Производился ли перезапуск/очистка кэша приложения?

С уважением, Анна Алимова
Эксперт III линии технической поддержки Terrasoft


1.созданная мной
2.wnd_BaseGridArea
3.да/да

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

Спасибо.

скрин

Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Для того чтобы добавить действие «Создать документ на основании договора» в раздел [Договоры] необходимо придерживаться следующего алгоритма:
1. Запустить Terrasoft Administrator.
2. Открыть сервис wnd_ContractsWorkspace. Перейти на закладку «Невизуальные», выделить компонент amiActions. Добавить новый ActionMenuItem:
o1

Заполнить свойства следующим образом:
o2

Сохранить изменения.
3. Перейти на закладку «События». Для добавленного компонента amiDocumentByContract создать обработчик события OnExecute:
o4

В теле функции обработки события прописать код:

FUNCTION amiDocumentByContractOnExecute(ActionMenuItem, Sender) {
         var ContractIDs = BaseWorkspace.Grid.SelectedIDs;
            var Count = ContractIDs.Count;
            IF (!Count||IsDatasetEmpty(dlContracts.Dataset)) {
                        ShowWarningDialog(GridNotContainsAnyRecords);
                        RETURN;
            }
            IF (Count > 1) {
                        var Message = FormatStr(GridContainsSomeRecords, Count);
                        IF (ShowConfirmationDialog(Message) == mrYes) {
                                   CreateDocumentByContract(ContractIDs);
                        }
            } else {
                        CreateDocumentByContract(ContractIDs);
            }
}

В этом же скрипте (wnd_ContractsWorkspaceScript) реализовать функцию FUNCTION CreateDocumentByContract(ContractIDs)

FUNCTION CreateDocumentByContract(ContractIDs) {
            var ContractDataset = dlContracts.Dataset;
            FOR (var i=0; iContractIDs.Count; i++) {
                        var Dataset = Services.GetSingleItemByUSI(ContractDataset.USI);
                        var ContractID = ContractIDs.Items(i);
                        ApplyDatasetIDFilter(Dataset, ContractID, true);
                        Dataset.DisableEvents();
                        Dataset.Open();
                        var DefaultValues = GetNewDictionary();
                        var NamedArray = GetDatasetFieldsValuesNamedArray(Dataset, new Array(
                                   'OwnerID', 'ContactID', 'CampaignID', 'OpportunityID',                            
                                   /* MODULE PROJECTS */ 'ProjectID'/* ENDMODULE PROJECTS */));
                        AddNamedArrayToDictionary(NamedArray, DefaultValues);
                        var InvoiceDate = GetFieldValueFromDisabledField(Dataset, 'StartDate');
                        var ContractID = GetFieldValueFromDisabledField(Dataset, 'ID');
                        Dataset.Close();
                        Dataset.EnableEvents();
                        DefaultValues.ADD('ContractID', ContractID);
                        DefaultValues.ADD('InvoiceDate', InvoiceDate);
                        var Attributes = GetNewDictionary();
                        Attributes('IsCreatedByContractID') = ContractID;
                        CreateNewWindowEdit(Self, 'wnd_DocumentEdit', DefaultValues, Attributes);
                       
            }
}

Таким образом скрипт будет иметь вид:
o5

4. Сохранить все внесенные изменения. Перезапустить приложение Terrasoft. Проверить работу функционала.

Перед внесением изменений в конфигурацию настоятельно рекомендуем создать резервную копию БД.

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

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

У меня такой же вопрос

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

Правку кода в разделе не предлагать? :wink:

 

"Александр Кудряшов" написал:Правку кода в разделе не предлагать?

Предложите

Возможно варианты.
Если требуется ограничить доступ конкретным пользователям/группам на известные действия, можно в скрипте к разделу в обработчике OnPrepare просто прятать действия по условиям:

    amiCreateTask.IsVisible = (..проверка условий..);

Если нужен более формальный инструмент, то есть возможность раздачи прав любому пользователю/группе на любое действие, то нужны доработки помасштабнее, например:
- сделать в разделе "Администрирование" новую вкладку "Права на действия", и написать код, который определяет список действий в каждом разделе, и хранит права на них;
- модифицировать scr_BaseWorkspace, который станет "прятать" действия в зависимости от прав текущего пользователя.
--------------------------------------------
Лабитек
Центр разработки приложений
[update: :wink:]

Ну вариантов много в общем.. самый прямолинейный делаем группы пользователей и дорабатываем метод amiActionsOnPrepare в нужном разделе, определяя группу текущего пользователя и включая/выключая для него свойство IsVisible для соответствующих ActionMenuItem.

[update: надо мне было быстрее печатать]

 

Войдите или зарегистрируйтесь, чтобы комментировать