Добрый день.

Есть необходимость скрывать кнопку "+" (кнопка добавления записи) на детали, в зависимости от того, на какой странице она находится.

1.На странице контакта, кнопки "+" никогда не должно быть.

2. На странице заявки, кнопки "+" никогда не должно быть.

3. На преднастроенной странице БП, кнопка должна отображаться, в зависимости от наличия записи в этой детали, по определенным типам и т.д.

Реализовали следующую логику:

На схеме детали создано сообщение, которое срабатывает на Init. Передаем сообщение с параметрами. В ответ получаем:

1. Если открываем страницу контакта, то там срабатывает подписка и всегда передаем false

2. Если открываем страницу заявки, то там срабатывает подписка и всегда передаем false

3. Если открываем преднастроенную страницу, срабатывает подписка, дальше срабатывает функция которая делает проверку наличия записей в таблице детали, с определенными параметрами, и если запись есть передаем false если записей нету передаем true

 

Вроде все работает. Но заметили, что если сначала открыть страницу Контакта или Заявки, а потом открыть преднастроенную страницу, то подписка на преднастроенной странице не отрабатывает, а отрабатывает именно Контакт (либо заявка), и соответсвеноо получаем false. 

Т.е. при ините странице контакта, срабатывает подписка, которая "висит" и отвечает постоянно отвечает всем подряд.

 

Можно ли как-то отменять подписку, после "ухода" со страницы? Именно ухода, не по нажатию кнопки закрыть (я так понимаю тут можно пойти через destroy) ? 

 

Или есть какие-то еще варианты?

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

Нравится

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

А мы просто делаем 2 разные схемы детали на одном объекте. Одна с "+", другая без него (а ещё без Copy, Import и т.п.)



И используем на странице ту, которая нужна

Владимир Соколов,

Да, тоже пришли в итоге к этом варианту. Но думали немного "покопать" в сторону универсального решения)

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

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

 

Столкнулся с проблемой вызова sandbox из детали т.е. заходя из раздела на страницу подписка срабатывает, но если на страницу зайти из детали то нет.

Нравится

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

Поясните пожалуйста где находятся подписки?

Кисловский Михаил Андреевич,

вызывают из схемы детали "Schema5Detail", передают в схему открываемой страницы "...1Page"

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

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

Добрый день!

Столкнулся с проблемой публикации данных из секции в модуль.

В секции обьявил данный метод который публикует фильтры в другой модуль.

....
afterFiltersUpdated: function() {
				this.callParent(arguments);
				debugger;
				var previousDate = new Date();
				previousDate.setDate(previousDate.getDate() - 1);
 
				var StartDate = "";
				var StopDate = "";
 
				var fixedFilters = this.get("SectionFiltersValue").collection.get("FixedFilters");
				var customFilters = this.get("SectionFiltersValue").collection.get("CustomFilters");
				StartDate = fixedFilters.PeriodFilter.startDate === null ? 
					Ext.Date.format(previousDate, "Y-m-d") :
					typeof (fixedFilters.PeriodFilter.startDate) === "string" ? 
					Ext.Date.format(new Date((new Date(fixedFilters.PeriodFilter.startDate.substr(0, 10))))) : 
					Ext.Date.format(new Date(), "Y-m-d");
				StopDate = fixedFilters.PeriodFilter.dueDate === null ? 
					Ext.Date.format(previousDate, "Y-m-d") :
					typeof (fixedFilters.PeriodFilter.dueDate) === "string" ? 
					Ext.Date.format(new Date((new Date(fixedFilters.PeriodFilter.dueDate.substr(0, 10))))) : 
					Ext.Date.format(new Date(), "Y-m-d");
 
					var dataSend = {
						StartDate: StartDate,
						StopDate: StopDate
					};
 
					this.sandbox.publish("UpdateInsurerAnalyticWidget", dataSend, ["AbInsurerAnalyticWidgetUpdated"]);
			},
....

 

define("AbInsurerAnalyticByZoneModule", ["ext-base", "terrasoft", "sandbox", "BaseFiltersGenerateModule", "AbInsurerAnalyticByZoneModuleResources", "ChartModuleHelper", "css!AbInsurerAnalyticByZoneModuleCSS", "ServiceHelper"],
	function(Ext, Terrasoft, sandbox, BaseFiltersGenerateModule, resources, ChartModuleHelper, css, ServiceHelper, ConfigurationConstants) {
		function getViewModel() {
			return Ext.create("Terrasoft.BaseViewModel", {
				entitySchema: "AbInsurance",
				methods: {
					init: function() {},
					getChart: function(key) {
						sandbox.publish("GenerateChart", key);
 
					},
					load: function() {}
				}
			});
		}
		var result = "";
		function generateMainView(renderTo) {
 
			var resultConfig = Ext.create("Terrasoft.Container", {
				id: "tableInsurerAnalyticByZoneParamContainer",
				selectors: {
					wrapEl: "#tableInsurerAnalyticByZoneParamContainer"
				},
				renderTo: renderTo
			});
			return resultConfig;
		};
		function getAnalyticByZone(parameters) {
			var serviceData = {
				startDate: parameters[0].toString(),
				stopDate: parameters[1].toString()
			};
 
			ServiceHelper.callService("AnalyticsProcessingService", "GetAnalyticDashboardData",
				function (response) {
					debugger;
					var htmlAdded = resources.localizableStrings.HeaderTable;
					if (response.status === 404 || response.status === 500 || response.status === 400) {
						Terrasoft.showErrorMessage("\t Error: \n" + response.message);
					}
					else if(response.GetAnalyticDashboardDataResult.length > 0){
						result = response.GetAnalyticDashboardDataResult;
						for(var i = 0; i < result.length; i++){
							var segment = result[i].Segment;
							var avgRevenue = result[i].AvgRevenue;
							var salesCount = result[i].SalesCount;
							var cpa = result[i].Cpa;
							var sumCtr = result[i].SumCtr;
							var cr = result[i].Cr;
							var roas = result[i].Roas;
							var tableBody = resources.localizableStrings.TableBody;
							htmlAdded += Ext.String.format(tableBody,segment,avgRevenue,salesCount,cpa,sumCtr,cr,roas);
						}
					} else {
						result = null;
					}
					htmlAdded += "</table>";
					Ext.get("tableInsurerAnalyticByZoneParamContainer").setHTML(htmlAdded);
				}, serviceData, this);
		}
		function getReplaceString(str, separator){
		var arSt = str.split(separator);
			var res = arSt[2] + separator + arSt[1] + separator + arSt[0];
			while(res.indexOf(separator) > 0){
				res = res.replace(separator,"-");
			}
			return res;
		}
 
		var render = function(renderTo) {
			var viewConfig = generateMainView(renderTo);
			var viewModel = getViewModel();
			var getStartD = Ext.get("fixedFilterCreatedAtView-wrap").dom.innerText;
			var getEndD = Ext.get("fixedFilterCreatedAtDueView-wrap").dom.innerText;
			var date = new Date();
			var startD = getStartD.indexOf("Начало") > 0 ? Ext.Date.format(date, "Y-m-d") : getReplaceString(getStartD, ".");
			var endD = getEndD.indexOf("Завершение") > 0 ? Ext.Date.format(date, "Y-m-d") : getReplaceString(getEndD, ".");
			var ar = [];
			ar.push(startD);
			ar.push(endD);
			getAnalyticByZone(ar);
			viewConfig.bind(viewModel);
		};
		return {
			schema: "AbInsurance",
			mesages: {
				"UpdateInsurerAnalyticWidget": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.SUBSCRIBE
			},
			},
			methods: {
 
			},
			userCode: function() {},
			init: function() {
				debugger;
				sandbox.subscribe("UpdateInsurerAnalyticWidget", function(arg) {
 
					var arArg = [];
					arArg.push(arg.StartDate);
					arArg.push(arg.StopDate);
					getAnalyticByZone(arArg);
				}, this, ["AbInsurerAnalyticWidgetUpdated"]);
			},
			render: render
		};
	}
);

в данном модуле в init сделал подписку, но она не отрабатывает при изменении фильтров.

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

Нравится

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

Алексей, не вижу в примерах кода вызова sandbox.registerMessages(messageConfig) для регистрации сообщений модуля. Проверьте, всё ли правильно в Ваших разработках, ориентируясь на инструкцию «Обмен сообщениями между модулями» в академии.

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

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



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

ошибок в консоли нет, но функция внутри subscribe не отрабатывает.



подскажите, проблема в том, что я пытаюсь получить сообщение на другой странице или в чем-то другом?)

Нравится

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

Если открываете новый раздел в другом окне или вкладке браузера, то sandbox между ними не передаёт, нужно отправлять при помощи ClientMessageBridge. Если всё в одной вкладке и не работает, возможно, не тот sandbox.id (как его смотреть, см. тут). Также см. следующие статьи по обмену сообщениями, может что-то ещё не учли.

Зверев Александр,

Спасибо за ответ!



Дополнение к ответу на собственный вопрос: кроме указанных Александром моментов есть еще один важный - сначала нужно подписаться на сообщение, а потом его отправлять (иначе сообщение некому получать)

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

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

Нравится

2 комментария
Лучший ответ

Добрый день!

Деталь можно обновить следующим кодом:

this.updateDetail({detail: "DetailName"});

 

Добрый день!

Деталь можно обновить следующим кодом:

this.updateDetail({detail: "DetailName"});

 

Сидоров Александр В.,

Спасибо, добавил reloadAll: true и заработало)

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

Добрый день. Есть такая задача:  в совмещённом режиме продублировать кнопку, которая будет устанавливать дату в поле в карточке. Кнопку я добавил, но не могу установить значение в поле карточки. Пытался сделать через sandbox следующим образом:

В Section:

 messages: {

            "MessagePublish": {

                mode: Terrasoft.MessageMode.BROADCAST,

                direction: Terrasoft.MessageDirectionType.PUBLISH

            }

        },

............

        methods: {

            //обработчик кнопки

            onSetDateTimeForPageClick: function () {

                this.sandbox.publish("MessagePublish");

            }

         }

В Page:

 messages: {

            "MessagePublish": {

                mode: Terrasoft.MessageMode.BROADCAST,

                direction: Terrasoft.MessageDirectionType.SUBSCRIBE

            },

        },

        init: function () {

            this.callParent(arguments);

            this.sandbox.subscribe("MessagePublish", this.methods.onSetDateTimeClick, this);

        },

Что я упустил или неправильно делаю?

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

 

Нравится

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

Добрый день.

Если дату вы передаете, то в publish нужно указать передаваемый аргумент. В subscribe callback-метод нужно записывать без «methods» (this.onSetDateTimeClick) – и соответственно он должен быть задан в methods страницы, и принимать параметр(в который придёт передаваемый аргумент). Больше примеров на академии https://academy.terrasoft.ru/documents/technic-sdk/7-11/sandbox-obmen-s…

VladKapitanchyk,

Добрый день, метод onSetDateTimeClick имеет следующее определение 

        onSetDateTimeClick:function(){

                this.set("UsrDateTime",(new Date).toString());

            }

Где UsrDateTime текстовое поле карточки. То есть, вызов происходит без аргументов, из Section я всего лишь хочу дать сигнал, чтобы на Page вызвался метод. Исправил в subscribe callback-метод на (this.onSetDateTimeClick), но это не помогло. Также попробовал переделать на способ с передачей аргументов, и тоже не помогло(

Полный листинг способа без передачи аргумента:

В Section:

define("UsrClientModule21Section", [], function () {

    return {

        entitySchemaName: "UsrClientModule2",

        details: /**SCHEMA_DETAILS*/ {} /**SCHEMA_DETAILS*/ ,

        messages: {

            "MessagePublish": {

                mode: Terrasoft.MessageMode.BROADCAST,

                direction: Terrasoft.MessageDirectionType.PUBLISH

            }

        },

        diff: /**SCHEMA_DIFF*/ [{

            "operation": "insert",

            "parentName": "CombinedModeActionButtonsCardLeftContainer",

            "propertyName": "items",

            "name": "SetDateTimeButton",

            "values": {

                "itemType": Terrasoft.ViewItemType.BUTTON,

                "caption": {

                    bindTo: "Resources.Strings.SetDateTime"

                },

                "click": {

                    bindTo: "onSetDateTimeClick"

                },

                "style": Terrasoft.controls.ButtonEnums.style.GREEN,

            }

        }] /**SCHEMA_DIFF*/ ,

        methods: {

            onSetDateTimeClick: function () {

this.sandbox.publish("MessagePublish");

//Способ с передачей аргумента.

//this.sandbox.publish("MessagePublish",(new Date).toString());

            }

        }

    };

});

В Page:

define("UsrClientModule21Page", [], function() {

    return {

        entitySchemaName: "UsrClientModule2",

        details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,

        modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,

        messages: {

            "MessagePublish": {

                mode: Terrasoft.MessageMode.BROADCAST,

                direction: Terrasoft.MessageDirectionType.SUBSCRIBE

            },

        },

        init: function () {

            this.callParent(arguments);

            this.sandbox.subscribe("MessagePublish", this.onSetDateTimeClick, this);

//При передаче аргумента

// this.sandbox.subscribe("MessagePublish", function(arg)..{this.set("UsrDateTime",arg)}, this);

        },

        diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,

        methods: {

            onSetDateTimeClick:function(){

                this.set("UsrDateTime",(new Date).toString());

            }

        },

        rules: {},

        businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/

    };

});

Добрый день.

Метод "init" должен быть в блоке "methods".

Так же рекомендую открывать консоль (F12) и читать ошибку, если будет что то наподобе "Cannot read property 'entitySchemaName'" значит проблема с неправильной структурой схемы.

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

Добрый день!

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

addRecord: function(editPageUId) {
        this.sandbox.publish("PublishDetailName", "ilaySchema6Detail", [this.sandbox.id]);
        this.callParent(arguments);
}

subscribeSandboxEvents: function() {
        this.callParent(arguments);
        var detailId = "SectionModuleV2_ilayDiagnosisSection_CardModuleV2_detail_ilayRecomendation46fde591d61eilayRecomendationilayilayRecomendation1Page";
        this.sandbox.subscribe("PublishDetailName", this.getDetailNameFromWhoOpen, this, ["CardModuleV2_ilayDiagnosisPage_detail_ilayRecomendation46fde591d61eilayRecomendationilayilayRecomendation1Page"]);
},

getDetailNameFromWhoOpen: function(detailName) {
        var a = 5;
}

Не вызывается метод "getDetailNameFromWhoOpen", т.к. скорее всего неправильно задан 4-й параметр метода ["CardModuleV2_..."]. Подскажите, как быть!

Нравится

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

Здравствуйте.
Рекомендуем посмотреть соседнюю тему:
http://www.community.terrasoft.ru/forum/topic/15210

Эту тему находил, но там не совсем понятен принцип формирования тега (4-й параметр в методе "subscribe"). Также находил различные примеры в других проектах на 7.6 и 7.7 версиях, но какого-то определенного правила не нашел для того, чтобы правильно задать сигнатуры методов "sandbox" - каждый пример реализован слишком не так, как остальные.

Если конкретно рассмотреть код:

this.sandbox.subscribe("PublishDetailName", this.getDetailNameFromWhoOpen, this, ["CardModuleV2_..."]);

теоретически, 4-й параметр ["CardModuleV2_..."] является идентификатором именно этого сообщения, которое должно быть получено из:

this.sandbox.publish("PublishDetailName", "ilaySchema6Detail", [this.sandbox.id]);

, где этим идентификатором для метода "publish" является 3-й параметр.

Так ли это? Подчеркну, что задачей является передача сообщения из детали на карточку редактирования этой детали.

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

Допустим так... А вот название этой переменной-идентификатора - оно какое-то особое по составу? Или можно абсолютно произвольным его задать? Суть в том, что при выполнении всего выше указанного, метод не вызывается! Почему, собственно, и была создана эта тема.

Не совсем понял про название переменной-идентификатора.

Вот рабочий пример кода для общения страницы редактирования с деталью:

Код для страницы контрагента.

Объявляем сообщение:

messages:{
	"PublishDetailName": {
		mode: Terrasoft.MessageMode.PTP,
		direction: Terrasoft.MessageDirectionType.SUBSCRIBE
	}
},

Подписываемся на сообщение в методе init:

methods: {
	init: function(){
		this.callParent(arguments);
		var sandboxId = this.sandbox.id + '_detail_LTSTestDetail';
		console.log(sandboxId);
		this.sandbox.subscribe("PublishDetailName", function(){
			this.set("Name", "Great");
		}, this, [sandboxId]);
	}
},

Код для страницы редактирования детали.

Объявляем сообщение:

messages: {
	"PublishDetailName": {
		mode: Terrasoft.MessageMode.PTP,
		direction: Terrasoft.MessageDirectionType.PUBLISH
	},
},

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

methods: {
	init: function(){
		this.callParent(arguments);
		var scope = this;
		var id = this.sandbox.id;
		var detailId = id.substring(0, id.indexOf('32c1bacf5d43LT'));
		console.log('detailId ' + detailId);
		this.on("change:LTSSTRING", function(){
			var val = this.get("LTSSTRING");
			if(val === 'test'){
				scope.sandbox.publish("PublishDetailName", { test: "test" }, [detailId]);
			}
		});
	}
},

В данном примере оба идентификатора равны CardModuleV2_a924f56e-85a8-4bd5-a388-0009571f7988_AccountPageV2_detail_LTSTestDetail

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

Версия BPMOnline 7.2

Простая задача: в зависимости от чекбокса на основной карточке разрешить или запретить добавление элементов в деталь.

1. В коде основной карточки:

добавим чекбокс на страницу

{
                                        type: Terrasoft.core.enums.ViewModelSchemaItem.ATTRIBUTE,
                                        name: 'IsProductChoose',
                                        columnPath: 'IsProductChoose',
                                        dataValueType: Terrasoft.DataValueType.BOOLEAN,
                                        visible: true,
                                        customConfig: {
                                                click: {
                                                        bindTo: "IsProductChooseClicked"
                                                }
                                        }
                                }

обработчик изменения чекбокса

this.methods.IsProductChooseClicked = function() {
                       
                        var args = {
                                param: this.get("IsProductChoose")
                        };
                        sandbox.publish(
                                "IsProductChooseChanged",
                                args,
                                [sandbox.id]
                        );
                };

2. В коде детали:

изменим конфиг выпадающего меню

this.modifyUtilsButton = function(utilsButton) {
                        var utilsMenuItems = utilsButton.menu.items;
                       
                        utilsMenuItems[1].caption = "Выбрать продукты";
                        utilsMenuItems[1].enabled = {bindTo: "isProductChooseForSelection"};
                        return utilsButton;
                };

обработчик "включить/выключить пункт меню"

this.methods.isProductChooseForSelection = function() {                
                        this.sandbox.subscribe("IsProductChooseChanged", function(arg) {
                                console.log(arg);
                        }, this, [this.getSenderSandboxId()]);
                };
               
                this.methods.getSenderSandboxId = function() {
                        return this.sandbox.id.replace('_detail_SynchronizedProduct', '');
                };

Однако при открытии карточки получаю ошибку в консоли браузера:
Uncaught Terrasoft.UnsupportedTypeException: Message IsProductChooseChanged is not defined in undefined module

К сожалению в документации не описано как работать с событиями через sandbox.

Буду благодарен за консультацию.

Нравится

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

как раз недавно обсуждались сообщения: http://www.community.terrasoft.ru/forum/topic/15210
по версиям, насколько я знаю, отличий нет

К сожалению, отличия есть. В 7.2 как минимум нет такого объекта Terrasoft.MessageMode.PTP

Для BPM'Online 7.2 Вы можете воспользоваться уже существующими месседжами, к примеру "UpdateDetail".

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

var moduleId = sandbox.id + '_detail_communications';
            this.on("change:Name", function(){
                if(this.get("Name") === "Some name"){
                    sandbox.publish('UpdateDetail', null, [moduleId]);
                }
            });

Код в методе "init" детали:

var moduleId = sandbox.id;
            sandbox.subscribe("UpdateDetail", function() {
                alert("GOAL!")
            }, [moduleId]);

Данный код тестировался для версий 720 и 722. Основное условие работоспособности - идентичность содержания переменной moduleId как для модуля так и для страницы редактирования.

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

Да, в версии 7.2 создавать месседжи можно только в модулях.

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

Нашел несколько примеров по сообществу применения функционала сообщений через SandBox.

Вот здесь: http://www.academy.terrasoft.ru/documents/docs/technic/SDK/7.4.1/ModuleDevelopmentInBPMonline.html
Содержится обещание

Более подробно механизм обмена сообщениями между модулями системы будет рассмотрен в отдельной статье SDK.

Статья не обнаружена. Просьба ткнуть носом или сообщить, что искать бесполезно..

Нравится

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

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

Вот пример общения между деталями через SandBox

define("AccountBillingInfoDetailV2", [], function() {
    return {
        entitySchemaName: "AccountBillingInfo",
        details: /**SCHEMA_DETAILS*/{
        }/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[
            {
                "operation": "merge",
                "name": "DataGrid",
                "values": {
                    "selectRow": {
                        "bindTo": "rowSelected"
                    }
                }
            }
        ]/**SCHEMA_DIFF*/,
        methods: {
            rowSelected: function() {
                this.sandbox.publish("RowSelectedInFirstDetail", { test: "param anything" }, [this.sandbox.id]);
                console.log("rowSelected in first detail...");
            }
        },
        messages: {
            "RowSelectedInFirstDetail": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.PUBLISH
            }
        }
    };
});
define("AccountAddressDetailV2", [], function() {
    return {
        entitySchemaName: "AccountAddress",
        details: /**SCHEMA_DETAILS*/{
        }/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
        methods: {
            init: function() {
                this.sandbox.subscribe("RowSelectedInFirstDetail", function(arg) {
                    console.log("test " + arg.test);
                }, this, [this.getSenderSandboxId()]);
            },
            getSenderSandboxId: function() {
                return this.sandbox.id.replace("_AccountAddress", "_AccountBillingInfo");
            }
        },
        messages: {
            "RowSelectedInFirstDetail": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.SUBSCRIBE
            }
        }
    };
});

Так же, в конфигурации Вы можете найти дополнительные примеры.

То есть примерно так:
Заявляем в блоке messages {} сообщение с одним наименованием, но с разным параметром направления(MessageDirectionType).

Отправляем сообщение из нужного модуля так:
this.sandbox.publish (A1,B1,C1)
A1 - Наименование сообщения, зарегистрированного в messages
B1 - массив параметров
C1 - Id сообщения, обычно = this.sandbox.id

Ловим в нужном модуле сообщение так:
this.sandbox.subscribe(A2, B2, C2, D2);
A2 - Наименование сообщения, зарегистрированного в messages
B2 - Некая функция, принимающая массив параметров в "arg" и что-то делающая полезное
С2 - объект, содержащийся в модуле-получателе.. (в обычном случае this )
D2 - ссылка на метод, возвращающий чтото?

Вот насчет последнего - мне пока не понятно.. Можете дать пояснение?

Алексей, добрый день!

Отдельной статьи по сообщениям в SDK на данный момент нет.

Ок. А может, тогда подскажете иное решение, как передать Контрагента ( Account_id) В деталь Продукты в заказе?
Я пытаюсь сделать это через sandbox, правильно ли это и есть ли более правильные пути?

"Шестаков Алексей Владимирович" написал:

Ок. А может, тогда подскажете иное решение, как передать Контрагента ( Account_id) В деталь Продукты в заказе?

Я пытаюсь сделать это через sandbox, правильно ли это и есть ли более правильные пути?

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

"Мотков Илья" написал:D2 - ссылка на метод, возвращающий чтото?
Вот насчет последнего - мне пока не понятно.. Можете дать пояснение?

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

А поскольку "this.sandbox.id" у разных схем разный, то метод этот "getSenderSandboxId" призван сгенерировать такой же идентификатор, как и у схемы, которая публикует сообщение.

Что именно содержится в this.sandbox.id, для каждой их схем, вы можете посмотреть в режиме отладки (F12) в вашем браузере. И на основании увиденного, подумать, как привести Id песочницы слушателя, к Id песочницы схемы публикации.

"Щиголь Максим" написал:Если у вас возникнут трудности с этим, можем написать пример именно по общению через sandbox страницы детали и страницы карточки.

Надеюсь, справлюсь :)
Один только вопрос: сообщения хранятся в Sandbox пока его не прочитают, или только передается между модулями и они оба должны существовать в момент publish?

Спасибо, Максим..
Подскажите еще, пожалуйста, как правильно получить данные содержащиеся в this по пути в отладчике:

this.values.DefaultValues[0].value

this.get("Order"), а именно заказ я там вижу в данном случае, не помогает.. а указывать как выше сделано, явно некошерно.

"Шестаков Алексей Владимирович" написал:
Один только вопрос: сообщения хранятся в Sandbox пока его не прочитают, или только передается между модулями и они оба должны существовать в момент publish?

Оба должны быть живы (прошли свой init, и еще не выгружены из песочницы) в момент публикации сообщения.
Когда происходит publish сообщения, sandbox смотрит есть ли кто-то из ныне живых, слушающий тот же Id песочницы что и публикующий, и, если такого находит, дает ему сообщение.

Но в вашем случае, когда вы открываете страницу редактирования детали из страницы карточки, страница карточки не удаляется, так что страница карточки и детали, могут общаться через sandbox.

На ваш второй вопрос, отвечу комментарием ниже.

"Шестаков Алексей Владимирович" написал:Подскажите еще, пожалуйста, как правильно получить данные содержащиеся в this по пути в отладчике:

Не совсем понятно задан вопрос, но постараюсь предположить что вас интересует, как в карточке заказа, получить id контрагента, что бы его передавать дальше по sandbox.

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

Второе, это не должен быть метод init, в нем еще не заполнены поля. Можете для целей отладки использовать метод onEntityInitialized, или onSaved, что бы посмотреть что за поля есть у заказа.

Так же учтите что в 7.7. в заказе можно покупателем указать как контакт, так и аккаунт, в зависимости от этого и получать их необходимо будет по разному,
так: this.get("Account") для контрагента,
и так: this.get("Contact") для контакта.

Вот, думаю по скриншоту станет понятно:

В точку! Именно на Init я и застрял. :smile:

Понимание происходящего так и не пришло.. Прошу о помощи... что было сделано... В карточке заказа:

define("OrderPageV2", ["OrderPageV2Resources", "GeneralDetails", "OrderConfigurationConstants",
	"BusinessRuleModule", "MoneyModule", "VisaHelper",  "ProcessModuleUtilities", "MaskHelper"],
function(Resources, GeneralDetails, OrderConfigurationConstants, BusinessRuleModule, MoneyModule,
	VisaHelper, ProcessModuleUtilities, MaskHelper) {
return {
...
methods: {
	onEntityInitialized: function() {
		this.sandbox.publish("GetAccountInOrderId", { AccId: this.get("Account").value, AccDisp: this.get("Account").displayValue}, [this.sandbox.id]);
		this.callParent(arguments);
	},			
	...
messages: {
	"GetAccountInOrderId": {
	mode: Terrasoft.MessageMode.PTP,
	direction: Terrasoft.MessageDirectionType.PUBLISH
}

В карточке добавляемого в заказ продукта:

define("OrderProductPageV2", ["BaseFiltersGenerateModule", "OrderProductPageV2Resources", "GeneralDetails", "ConfigurationConstants"],
function (BaseFiltersGenerateModule, resources, GeneralDetails, ConfigurationConstants) {
return {
...
methods : {
	onEntityInitialized : function () {
		var ContrId;
		var ContrName;
		this.sandbox.subscribe("GetAccountInOrderId", function (acc) {
			ContrId = acc.AccId;
			ContrName = acc.AccName
		}, this, [this.getSenderSandboxId]);
		this.callParent(arguments);
	},
	getSenderSandboxId : function () {
		return this.sandbox.id.replace("_SectionModuleV2_OrderSectionV2_CardModuleV2_detail_ProductOrderProductOrderProductPageV200000000-0000-0000-0000-000000000000", "_SectionModuleV2_OrderSectionV2_CardModuleV2");
	},
	...
messages : {
	"GetAccountInOrderId" : {
		mode : Terrasoft.MessageMode.PTP,
		direction : Terrasoft.MessageDirectionType.SUBSCRIBE
	}

Переменные Contr - не заполняются.. :cry:
Смущает Guid.Empty в sandbox.id карточки редактирования записи детали. Но он там есть в отладчике..
И, результата все нет.. Может, неправильно выбраны методы?

Понятно, что в случае добавления новой записи Контрагент не заполнен на onEntityInitialized, тестирую на редактировании.

Guid.Empty это нормально для не сохраненного объекта, он не должен Вас смущать, более того, Вы очень грубо приводите id песочниц к единому виду. Уверен там разница минимальна, буквально в "OrderProductOrderProductPageV2", а заменять все, вместе с Guid-ом, тем более когда у карточки заказа в id песочницы явно все это остается, не стоит.

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

Строить Id песочницы вместе с Guid-ом открытой записи разумно для того, что бы, если у вас открыто несколько карточек, в нескольких закладках браузера, что бы на изменения одной, не реагировала деталь другой, и.т.д.

Но и это не главная ошибка.
Главная ошибка сейчас в том что вы делаете publish в методе onEntityInitialized карточки заказа, а в этот момент у вас еще не открыта даже деталь.

Еще одна ошибка, что Вы зачем-то вынесли значения переменных в начало метода onEntityInitialized карточки схемы. Они не заполнятся значениями никогда. Т.к. даже когда у вас сработает колбек месседжа подписки, то контекст его выполнения будет равен контексту объекта карточки, а не метода.

Заведите себе атрибуты в карточке детали, и заполняйте их в колбеке subscribe метода.
Либо, заполняйте сразу через this.set("имя поля") необходимые вам поля. Вы же наверно хотите заполнить какие-то поля детали автоматически? Так реализуйте вначале их. Если получаете Вы это значение не для поля, то тогда используйте атрибут.

В общем вам нужно построить приблизительно такой алгоритм:

1. В карточке заказа сделайте метод: ДетальПроситДанные() в теле которой публикуйте сообщение в песочницу с именем к примеру "ДанныеПоКонтрагентуДляДетали", и данными по контрагенту.

2. В карточке заказа сделайте подписку на сообщение, с именем к примеру "ДетальПроситДанные", в колбеке которой, дергайте свой метод ДетальПроситДанные()

3. В карточке детали в методе onEntityInitialized вначале подпишитесь на сообщение "ДанныеПоКонтрагентуДляДетали", в теле которой заполняйте свои атрибуты или поля. (собственно это результат всей нашей работы)

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

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

Максим, спасибо за терпение!
Уже почти результат достигнут :) Сейчас в Заказе такие методы:

sendAccountToOrderDetail: function() {
   this.sandbox.publish("GiveAccountToOrderDetail", {
      AccId: this.get("Account").value,
      AccDisp: this.get("Account").displayValue
   }, [this.sandbox.id]);
},
onEntityInitialized : function() {
   this.callParent(arguments);	
   this.sandbox.subscribe("AskAccountFromOrderDetail", this.sendAccountToOrderDetail(), this, [this.getSenderSandboxId]);
},
getSenderSandboxId : function() {
   return "SectionModuleV2_OrderSectionV2_CardModuleV2_detail_ProductOrderProductOrderProductPageV2";
},

sandbox.id Уже вставляю константой, скопировав из отладчика. пробовал как с Guid.Empty в конце id так и без него
Судя по всему именно с этим у меня сейчас проблема.
В детали так:

onEntityInitialized : function () {
   this.callParent(arguments);
   this.sandbox.subscribe("GiveAccountToOrderDetail", function (acc) {
      this.set("UsrContragents", {
         value : acc.AccId,
         displayValue : acc.AccDisp
      });
   }, this, [this.getSenderSandboxId]);
   this.sandbox.publish("AskAccountFromOrderDetail", null, [this.sandbox.id]);
},
 
getSenderSandboxId : function () {
   return "SectionModuleV2_OrderSectionV2_CardModuleV2";
},

И никак. :(

Воссоздал пример на своей базе.
Передаю на карточку детали "Продукт в заказе", сообщение из "Заказа". С значением Id контрагента заполненного в заказе.
Прилагаю полный листинг схем как карточки, так и детали.

define("OrderPageV2", ["OrderPageV2Resources", "GeneralDetails"],
function(resources, GeneralDetails) {
	return {
		entitySchemaName: "Order",
		details: /**SCHEMA_DETAILS*/{
		}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
		]/**SCHEMA_DIFF*/,
		attributes: {},
		methods: {
			onEntityInitialized: function() {
				this.callParent(arguments);
 
				this.sandbox.subscribe("OrderProductPageAsksForData", function(arg) {
					console.log("OrderProductPageV2 запрашивает данные прямо сейчас,");
					console.log("по Id песочницы: " + arg.sandboxId);
					// Высылаем данные.
					this.sendDataToOrderProductPage(arg.sandboxId);
				}, this, [this.sandbox.id]);
 
				console.log("Мы(OrderPageV2) подписались на сообщение: OrderProductPageAsksForData.");
				console.log("Id песочницы в этой карточке(OrderPageV2) следующий:");
				console.log(this.sandbox.id);
			},
			sendDataToOrderProductPage: function(sandboxId) {
				this.sandbox.publish("DataToOrderProductPage", { accountId: this.get("Account").value }, [sandboxId]);
				console.log("AccountId отправлен сообщением для OrderProductPageV2 по Id: " + sandboxId);
			}
		},
		rules: {},
		messages: {
			"DataToOrderProductPage": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.PUBLISH
			},
			"OrderProductPageAsksForData": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.SUBSCRIBE
			}
		},
		userCode: {}
	};
});

Схема детали:

define("OrderProductPageV2", ["BusinessRuleModule", "OrderUtilities"],
	function(BusinessRuleModule) {
		return {
			entitySchemaName: "OrderProduct",
			mixins: {},
			attributes: {},
			methods: {
				onEntityInitialized: function() {
					this.callParent(arguments);
 
					this.sandbox.subscribe("DataToOrderProductPage", function(arg) {
						console.log("OrderPageV2 передает нам данные!");
						alert("accountId: " + arg.accountId);
					}, this, [this.sandbox.id]);
 
					console.log("Мы(OrderProductPageV2) подписались на сообщение: DataToOrderProductPage.");
					console.log("По нашему(OrderProductPageV2) Id песочницы:");
					console.log(this.sandbox.id);
 
					this.sandbox.publish("OrderProductPageAsksForData", { 
						sandboxId: this.sandbox.id
					}, [this.getOrderPageSandboxId()]);
 
					console.log("Запросили данные у OrderPageV2, по её Id песочницы: " + this.getOrderPageSandboxId());
				},
				getOrderPageSandboxId: function() {
					var index = this.sandbox.id.indexOf("_detail_ProductInProducts");
					return this.sandbox.id.substring(0, index);
				}
			},
			messages: {
				"DataToOrderProductPage": {
					mode: Terrasoft.MessageMode.PTP,
					direction: Terrasoft.MessageDirectionType.SUBSCRIBE
				},
				"OrderProductPageAsksForData": {
					mode: Terrasoft.MessageMode.PTP,
					direction: Terrasoft.MessageDirectionType.PUBLISH
				}
			},
			diff: /**SCHEMA_DIFF*/[
			]/**SCHEMA_DIFF*/,
			rules: {
			}
		};
	}
);

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

Что является немного другой схемой, а именно схемой детали (OrderProductDetailV2), но, передача сообщений туда, по сути не сильно бы и отличалась. Главное понять саму механику работы с sandbox.

P.S. В результате работы вышеуказанного кода, в консоли браузера можно будет видеть:

Мы(OrderPageV2) подписались на сообщение: OrderProductPageAsksForData.
Id песочницы в этой карточке(OrderPageV2) следующий:
CardModuleV2_b8978c7f-a094-4943-bd13-2846b0ecbec9_OrderPageV2

Мы(OrderProductPageV2) подписались на сообщение: DataToOrderProductPage.
По нашему(OrderProductPageV2) Id песочницы:
CardModuleV2_b8978c7f-a094-4943-bd13-2846b0ecbec9_OrderPageV2_detail_ProductInProductsTabOrderProductOrderProductPageV200000000-0000-0000-0000-000000000000

OrderProductPageV2 запрашивает данные прямо сейчас,
по Id песочницы:
CardModuleV2_b8978c7f-a094-4943-bd13-2846b0ecbec9_OrderPageV2_detail_ProductInProductsTabOrderProductOrderProductPageV200000000-0000-0000-0000-000000000000
OrderPageV2 передает нам данные!

Ну и значение выведено алертом:

Вот это уже тянет на мануал.. Спасибо, Максим, обещаю вскоре отчитаться об успехе :)

Максим, я отразил весь ваш пример на своей базе и перепроверил и

Мы (OrderPageV2), Подписались на AskAccountFromOrderDetail, наш Sandbox.id: CardModuleV2_OrderPageV2
Мы(OrderProductPageV2) подписались на сообщение: GiveAccountToOrderDetail.
По нашему(OrderProductPageV2) Id песочницы: CardModuleV2_OrderPageV2_detail_ProductOrderProductOrderProductPageV200000000-0000-0000-0000-000000000000 
Запросили данные у OrderPageV2, по её Id песочницы: CardModuleV2_OrderPageV2

И ответ не приходит, заказ не получает сообщение и не отсылает в ответ контрагента.

В глаза бросается то, что sandbox.id в ваших логах содержит guid заказа, а в моем случае он передается и выглядит именно так, как написано в логах - без Guid. Как на Init, так и на другие события.

Версия BPM 7.5 - может это как-то влияет... следующим постом пришлю код..

Заказ:

		messages: {
			"GiveAccountToOrderDetail": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.PUBLISH
			},
			"AskAccountFromOrderDetail": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.SUBSCRIBE
			}
		},
...
onEntityInitialized : function() { // OrderPageV2
	this.callParent(arguments);
	this.sandbox.subscribe("AskAccountFromOrderDetail", function(arg) {
	    console.log("OrderProductPageV2 запрашивает данные прямо сейчас,");
  	    console.log("по Id песочницы: " + arg.sandboxId);
	this.sendAccountToOrderDetail(arg.sandboxId);
	}, this, [this.sandbox.id]);
	console.log("Мы (OrderPageV2), Подписались на AskAccountFromOrderDetail, наш Sandbox.id: " + this.sandbox.id);
},
sendAccountToOrderDetail: function(sandboxId) {
	this.sandbox.publish("GiveAccountToOrderDetail", {
		AccId: this.get("Account").value,
		AccDisp: this.get("Account").displayValue
	}, [sandboxId]);
	console.log("AccountId отправлен сообщением GiveAccountToOrderDetail для OrderProductPageV2 по Id: " + sandboxId);
},

Продукт:

		messages : {
			"GiveAccountToOrderDetail" : {
				mode : Terrasoft.MessageMode.PTP,
				direction : Terrasoft.MessageDirectionType.SUBSCRIBE
			},
			"AskAccountFromOrderDetail" : {
				mode : Terrasoft.MessageMode.PTP,
				direction : Terrasoft.MessageDirectionType.PUBLISH
			}
		},
...
onEntityInitialized: function() { // Карточка продукта в заказе
	this.callParent(arguments);
	this.sandbox.subscribe("GiveAccountToOrderDetail", function(arg) {
		this.set("UsrContragents", { value: arg.AccId, displayValue: arg.AccDisp }) 
		}, this, [this.sandbox.id]);
	console.log("Мы(OrderProductPageV2) подписались на сообщение: GiveAccountToOrderDetail.");
	console.log("По нашему(OrderProductPageV2) Id песочницы:" + this.sandbox.id);
	this.sandbox.publish("AskAccountFromOrderDetail", { sandboxId: this.sandbox.id }, [this.getOrderSandboxId]);
	console.log("Запросили данные у OrderPageV2, по её Id песочницы: " + this.getOrderSandboxId());
},
getOrderSandboxId : function() {
	var index = this.sandbox.id.indexOf("_detail_ProductOrder");
	return this.sandbox.id.substring(0, index); // обрезаем 
},

Уточнил версию :
Версия 7.5.0.1122

иногда sandbox.id в заказе бывает таким:
SectionModuleV2_OrderSectionV2_CardModuleV2
В зависимости от того, открыта ли слева в карточке заказа секция со списком заказов.
правда, на результат это не влияет.

На 7.5 проблема наблюдалась только в другом составлении ид песочницы для детали.
Получилось добиться получения ид контрагента изменением только метода getOrderSandboxId, ну и на всякий случай добавлением this. к типу и направлению сообщений.

define("OrderPageV2", ["OrderPageV2Resources", "GeneralDetails"],
function(resources, GeneralDetails) {
        return {
                entitySchemaName: "Order",
                details: /**SCHEMA_DETAILS*/{
                }/**SCHEMA_DETAILS*/,
                diff: /**SCHEMA_DIFF*/[
                ]/**SCHEMA_DIFF*/,
                attributes: {},
                methods: {
                        onEntityInitialized: function() {
                                this.callParent(arguments);
 
                                this.sandbox.subscribe("OrderProductPageAsksForData", function(arg) {
                                        console.log("OrderProductPageV2 запрашивает данные прямо сейчас,");
                                        console.log("по Id песочницы: " + arg.sandboxId);
                                        // Высылаем данные.
                                        this.sendDataToOrderProductPage(arg.sandboxId);
                                }, this, [this.sandbox.id]);
 
                                console.log("Мы(OrderPageV2) подписались на сообщение: OrderProductPageAsksForData.");
                                console.log("Id песочницы в этой карточке(OrderPageV2) следующий:");
                                console.log(this.sandbox.id);
                        },
                        sendDataToOrderProductPage: function(sandboxId) {
                                this.sandbox.publish("DataToOrderProductPage", { accountId: this.get("Account").value }, [sandboxId]);
                                console.log("AccountId отправлен сообщением для OrderProductPageV2 по Id: " + sandboxId);
                        }
                },
                rules: {},
                messages: {
                        "DataToOrderProductPage": {
                                mode: this.Terrasoft.MessageMode.PTP,
                                direction: this.Terrasoft.MessageDirectionType.PUBLISH
                        },
                        "OrderProductPageAsksForData": {
                                mode: this.Terrasoft.MessageMode.PTP,
                                direction: this.Terrasoft.MessageDirectionType.SUBSCRIBE
                        }
                },
                userCode: {}
        };
});
define("OrderProductPageV2", ["BusinessRuleModule", "OrderUtilities"],
        function(BusinessRuleModule) {
                return {
                        entitySchemaName: "OrderProduct",
                        mixins: {},
                        attributes: {},
                        methods: {
                                onEntityInitialized: function() {
                                        this.callParent(arguments);
 
                                        this.sandbox.subscribe("DataToOrderProductPage", function(arg) {
                                                console.log("OrderPageV2 передает нам данные!");
                                                alert("accountId: " + arg.accountId);
                                        }, this, [this.sandbox.id]);
 
                                        console.log("Мы(OrderProductPageV2) подписались на сообщение: DataToOrderProductPage.");
                                        console.log("По нашему(OrderProductPageV2) Id песочницы:");
                                        console.log(this.sandbox.id);
 
                                        this.sandbox.publish("OrderProductPageAsksForData", { 
                                                sandboxId: this.sandbox.id
                                        }, [this.getOrderPageSandboxId()]);
 
                                        console.log("Запросили данные у OrderPageV2, по её Id песочницы: " + this.getOrderPageSandboxId());
                                },
                                getOrderPageSandboxId: function() {
                                        var index = this.sandbox.id.indexOf("_detail");
                                        return this.sandbox.id.substring(0, index);
                                }
                        },
                        messages: {
                                "DataToOrderProductPage": {
                                        mode: this.Terrasoft.MessageMode.PTP,
                                        direction: this.Terrasoft.MessageDirectionType.SUBSCRIBE
                                },
                                "OrderProductPageAsksForData": {
                                        mode: this.Terrasoft.MessageMode.PTP,
                                        direction: this.Terrasoft.MessageDirectionType.PUBLISH
                                }
                        },
                        diff: /**SCHEMA_DIFF*/[
                        ]/**SCHEMA_DIFF*/,
                        rules: {
                        }
                };
        }
);

Если не получится и так, остается только обращаться в support@terrasoft.ru, с предоставлением учетных данных для доступа к Вашему сайту, где будет написано все вышесказанное в замещающих схемах, и останется только найти проблему, почему в конкретно вашем случае messages не отрабатывают. т.к. выше указанный код работоспособен.

Заработало! Допилил присвоение в карточке, все закрутилось-завертелось!
Большое спасибо!
Заодно получился ПочтиМануал :)

P.S. Методом массированного научного тыка обнаружилось, что в 7.7 можно получить однократно при сбросе кеша и полной перезагрузке в Chrome sandbox.id с Guid заказа.
Но при повторных обновлениях страницы или переходах по модулям Guid больше не показывается до следующего хард релоада.

Мы (OrderPageV2), Подписались на AskAccountFromOrderDetail, наш Sandbox.id: CardModuleV2_65a22318-a5ad-41e2-85a9-8c25393381e8_OrderPageV2

на 7.5 даже такого эффекта добиться не удалось :)

Максим, Добрый день! Пытаюсь в BPM 7.7 в карточке Документы сделать передачу Id контрагента в деталь с редактируемым реестром. Id аккаунта необходим для фильтрации контактов, которые выбираются на детали. Использую Ваш пример. Но в моем случае, все что находится в methods не отрабатывает. Для теста добавил функцию init, а ней debugger, функция не была вызвана.
Но правило из rules работает. Т.е. добавляю атрибут Account, значение пишу туда руками и контакты фильтруются по этому значению.
Код карточки Документы:

define('DocumentPageV2', ['DocumentPageV2Resources', 'GeneralDetails', 'BusinessRuleModule'],
function(resources, GeneralDetails, BusinessRuleModule) {
	return {
		entitySchemaName: 'Document',
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
 
]/**SCHEMA_DIFF*/,
		attributes: {
			"UsrType": {
				dependencies : [{
					columns : ["UsrDocumentType"],
					methodName : "onDocumentTypeChanged"
				}]
			},
		},
		messages: {
			"UsrDocumentTypeColumnChanged": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.PUBLISH
			},
			"DataToContactInDocumentPage": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.PUBLISH
			},
			"ContactInDocumentPageAsksForData": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.SUBSCRIBE
			}
		},
		methods: {
			onEntityInitialized: function() {
				this.callParent(arguments);
				this.sandbox.subscribe("ContactInDocumentPageAsksForData", function(arg) {
					// Высылаем данные.
					this.sendDataToContactInDocumentPage(arg.sandboxId);
				}, this, [this.sandbox.id]);
			},
			sendDataToContactInDocumentPage: function(sandboxId) {
				this.sandbox.publish("DataToContactInDocumentPage", { accountId: this.get("Account").value }, [sandboxId]);
			}
		},
		rules: {
 
		}
	};
});

Код карточки детали:

define("ContactInDocumentPageV2", ["BusinessRuleModule"], function(BusinessRuleModule) {
	return {
		entitySchemaName: "ContactInDocument",
		attributes: {
			"Account": {
				dataValueType: Terrasoft.DataValueType.STRING,
				type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				value: ""
			},
		},
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		messages: {
			"DataToContactInDocumentPage": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.SUBSCRIBE
			},
			"ContactInDocumentPageAsksForData": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.PUBLISH
			}
		},
		methods: {
			onEntityInitialized: function() {
				this.callParent(arguments);
				this.sandbox.subscribe("DataToContactInDocumentPage", function(arg) {
					this.set("Account", arg.accountId);
				}, this, [this.sandbox.id]);
				this.sandbox.publish("ContactInDocumentPageAsksForData", { 
					sandboxId: this.sandbox.id
				}, [this.getDocumentPageSandboxId()]);
			},
			getDocumentPageSandboxId: function() {
				var index = this.sandbox.id.indexOf("_detail");
				return this.sandbox.id.substring(0, index);
			}
		},
		rules: {
			"UsrContact": {
				FiltrationUsrContactByAccount: {
					ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
					autocomplete: true,
					autoClean: true,
					baseAttributePatch: "Account",
					comparisonType: Terrasoft.ComparisonType.EQUAL,
					type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
					attribute: "Account"
				}
			}
		}
	};
});

Помогите, пожалуйста, разобраться.

"Эмин Юнусов" написал:Помогите, пожалуйста, разобраться.

Методы из пейджа действительно работать не будут. Но вы можете написать свою фильтрацию колонки, написав её в атрибуте пейджа, в методе фильтрации. Примерно так:
http://www.community.terrasoft.ua/forum/topic/14388
Этот метод вызывается из пейджа, при работе редактируемого реестра, в момент создания конфига текущей строки.

"Мотков Илья" написал:
Но вы можете написать свою фильтрацию колонки, написав её в атрибуте пейджа, в методе фильтрации

Не получается передать accountId в функцию метода фильтрации. Через сообщение не выходит, т.к. метод завершает свою работу и функция в subscribe

this.sandbox.subscribe("DataToContactInDocumentPage", function(arg) {
                                        this.set("Account", arg.accountId);
                                }, this, [this.sandbox.id]);

вообще не отрабатывает.

Попробуйте заставить метод подождать результата. Объявите какой-нибудь флаг, и цикл пока флаг «ложь», по возвращению результата песочницей, меняйте флаг, и только тогда метод фильтрации вернет результат, с учетом того что вернула песочница.

function(query) {
  var r;
  myApi.exec('SomeCommand', function(response) {
    r = response;
  });
  while (!r) {}
  return r;
}
Показать все комментарии

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

1) Нужно передать значение (Id выбранной записи) со страницы детали в страницу проекта, задействованной в бизнес процессе. Я так понял нужно использовать sandbox и messages. Подскажите подробнее как их использовать?

2) Добавил на деталь свою кнопку. Как по нажатию этой кнопки осуществить дальнейшее прохождение страницы проекта по бизнес процессу. Банальный this.acceptProcessElement(); не помогает.

Скриншот во вложении.

Нравится

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

Добрый день!

Посмотрите похожие темы на community. Подобные задачи уже решались.
http://www.community.terrasoft.ru/forum/topic/11626
http://www.community.terrasoft.ru/forum/topic/13314
http://www.community.terrasoft.ru/blogs/12691
http://www.community.terrasoft.ru/forum/topic/10554

Здравствуйте. С первым вопросом разобрался. Удалось передать сообщение по нажатию кнопки. Но это не удобно. Скажите, а можно передать сообщение по событию выделения записи в детали(событие типа onClick)? Функцию получения выделенной строки - this.getActiveRow() нашел. А где прописать событие не разобрался.

И еще вопрос по messages. Как отловить на основной странице, что сообщение из детали пришло? Т.е есть ли такое событие прихода сообщения?

Решил реализовать следующим образом: добавить кнопку в активную строку и по нажатию послать сообщение основной форме. В основной форме отловит сообщение и отправиться дальше по процессу. Что удалось найти:

Нашел на форуме, что можно добавить кнопку в активную строку.

{
	"operation": "insert",
	"name": "DataGridActiveRowTestAction",
	"parentName": "DataGrid",
	"propertyName": "activeRowActions",
	"values": {
		"className": "Terrasoft.Button",
		"style": Terrasoft.controls.ButtonEnums.style.BLUE,
		"caption": {"bindTo": "Resources.Strings.TestRowButtonCaption"},
		"visible": true,
		"tag": "call"
	}
}

И потом переопределить метод onActiveRowAction:

onActiveRowAction: function(buttonTag, primaryColumnValue) {
	switch (buttonTag) {
		// замещение базового метода посылаем сообщение основной странице
		case "call":
			this.sandbox.publish("GetContactDetailActiveRecordId", this.get("TestParameter"),       [this.sandbox.id]);
			break;
		default:
			this.callParent(arguments);
			break;
	}
},

Который объявлен в BaseSectionV2 (Базовая схема раздела).

Проблема:
1) при объявлении кнопки выходит сообщение, что DataGrid не является контейнером для других объектов. Подскажите, что делаю не так?

2) Как отловить в основной форме, что пришло сообщение из детали?
За ранее спасибо.

Добрый день!

Для получения идентификатора текущей записи детали в родительской карточке редактирования используя механизм подписки/публикации сообщений между соответствующими модулями - алгоритм будет примерно следующий:

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

messages: {
"GetContactDetailActiveRecordId": {
mode: Terrasoft.MessageMode.PTP,
direction: Terrasoft.MessageDirectionType.SUBSCRIBE
}
}

Для детали точно так же, только в свойстве direction необходимо указать Terrasoft.MessageDirectionType.PUBLISH.

Далее при инициализации карточки редактирования (метод init) нужно подписаться на это сообщение, а в функции обратного вызова получить значение из детали и сохранить его в атрибут модели карточки:

init: function() {
this.callParent(arguments);
this.sandbox.subscribe("GetContactDetailActiveRecordId", function(recordId) {
this.set("ContactDetailActiveRecordId", recordId);
}, this, [contactDetailSandboxId]);
}

Значение contactDetailSandboxId Вам необходимо определить самостоятельно (оно формируется в зависимости от названия детали). В коде детали оно хранится в свойстве this.sandbox.id.

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

onButtonClick: function() {
this.sandbox.publish("GetContactDetailActiveRecordId", this.get("ActiveRow"), [this.sandbox.id]);
}

Здравствуйте, Олег.
Да, все получилось именно так, спасибо.

"Наконец, в коде детали, при обработке нажатия на кнопку необходимо просто опубликовать сообщение, передав значение текущей записи:"

Подскажите, как передать сообщение не по кнопке, а при выборе записи в DataGrid?

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

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

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

Здравствуйте, Алексей.
Хорошо. Понял. Подскажите а можно кнопку в DataGrid встроить? И как?

Добрый день!

Для удобства вы можете добавить кнопку рядом с базовыми кнопками детали. Пример замещающей схемы детали во вложении.
addbuttontodetail.txt

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

Олег, добрый день!

Попробуйте следующий вариант реализации:

в скрипте детали в блок diff добавить дополнительные свойства для DataGrid (название и заголовок кнопки привожу в качестве примера, Вы можете изменить их на свои):

{
	"operation": "merge",
	"name": "DataGrid",
	"values": {
		"activeRowAction": {"bindTo": "onActiveRowAction"},
		"activeRowActions": [
			{
				"className": "Terrasoft.Button",
				"style": this.Terrasoft.controls.ButtonEnums.style.BLUE,
				"markerValue": "myButtonAction",
				"tag": "myAction",
				"caption": "MyButton"
			}
		]
	}
}

После этого при выделении активной строки в детали должна появиться синяя кнопка с заголовком MyButton.

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

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

methods: {
	onActiveRowAction: function(buttonTag, primaryColumnValue) {
		if (buttonTag === "myAction") {
			// весь код ниже можно убрать, он демонстрирует, что значения
			// primaryColumnValue и activeRowId равны
			var activeRow = this.getActiveRow();
			var activeRowId = activeRow.get("Id");
			console.log(primaryColumnValue);
			console.log(activeRowId);
			// дальше Ваша реализация
			...
		}
	},
	...
}

Здравствуйте, Олег.
Спасибо. Получилось то, что нужно. Скрин во вложении.

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