Добрый день!

У меня есть деталь с редактируемым реестром. При добавлении в деталь записей обновляется реестр с помощью механизма сообщений, который сделан по этому примеру. Записи на деталь с помощью работы бизнес-процесса добавляются корректно и без ошибок.

ПРОБЛЕМА в том, что при добавлении записи на деталь вручную появляется ошибка .

Как исправить? (В обработчик события получения сообщения реестр детали обновляю вот так: this.updateDetail({detail: "UsrToursDetailGrid01695b42", realoadAll: true});)

И вообще, правильная ли у меня функция для обновления реестра?

Нравится

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

Либо удалять типа такой записи
ALTER TABLE [dbo].[qrtUsers]
drop constraint [FK7HPrCHgRbriWspbaL6QwqDxLWL0]

Либо разбираться в источнике проблемы

Dima Avdoshin,

Дело в том, что при отработке БП все нормально работает. А проблема именно при ручном добавлении. Я считаю, что удалять точно ничего не надо.

Павел, Вы правы, удалять связи точно не надо. Судя по сообщению, система пытается сохранить запись как новую, но при этом запись с таким Id уже есть. Вы редактировали ту самую, которую перед этим программно добавили или добавляли вручную совсем другую?

Возможно, после обновления при помощи обработчика есть какие-то отличия во внешнем виде детали, её кнопок?

 

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

Не редактирую, а добавляю новую. При редактировании ошибки нет.

Павел, этот Id 98c... принадлежит добавленной программно в БП записи в UsrTours? Его там же в процессе задают?

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

Нет. Запись с данным Id 98c833... - это запись, которую я добавляю вручную (нажимаю на + возле детали). А при добавлении с помощью БП все хорошо.

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

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

Спасибо! Обошел данную проблему другим способом.

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

Добрый день!

Согласно Т.З. необходимо реализовать следующие пункты...

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

БП создан и правильно добавляет записи в деталь. А что дальше делать? Как и куда что вставлять? Статей по механизму сообщений и Sandbox прочитал не мало, а в кучу собрать информацию для реализации своего задания не получается...

Нравится

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

Посмотрите данную статью, там есть пример https://academy.terrasoft.ru/docs/developer/front-end_development/webso…

 

Для обновления детали подойдет метод 

this.updateDetail({detail: "UsrDetail23d2c003", realoadAll: true})

Его запускать со страницы редактирования, где расположена нужная деталь.

Посмотрите данную статью, там есть пример https://academy.terrasoft.ru/docs/developer/front-end_development/webso…

 

Для обновления детали подойдет метод 

this.updateDetail({detail: "UsrDetail23d2c003", realoadAll: true})

Его запускать со страницы редактирования, где расположена нужная деталь.

Трефилов Павел Сергеевич,

Часть задания вроде бы как удалось сделать. А именно… Повторил в соответствии с примером применительно к своему заданию.

В объекте детали «Перечень работ» создал событийный подпроцесс, который срабатывает при добавлении записи в деталь, и передает Id новой записи детали. Сделал рассылку в созданном замещающем клиентском модуле с родителем ClientMessageBridge . Сделал подписку на сообщение в странице редактирования «Заказ на выполнение работ». Все работает, как и в примере.

Пока не получается обновить реестр детали. Делаю это следующим образом… В странице редактирования «Заказ на выполнение работ» в функции обработчике события полученного сообщения просто пишу this.reloadDetail("UsrListWorks"); (UsrListWorks – название объекта детали).

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

Pavel Litvinovich,

нужно писать не название объекта, а название делали в коде страницы. Смотрите блок details и там будет название детали. Пример:

		details: /**SCHEMA_DETAILS*/{
			"UsrMaterialDetail23d2c003": {
				"schemaName": "UsrMaterialDetail",
				"entitySchemaName": "UsrMaterial",
				"filter": {
					"detailColumn": "UsrParentMaterial",
					"masterColumn": "Id"
				}
			}
		}/**SCHEMA_DETAILS*/,

И еще я посмотрел как в последнем проекте делал обновление детали, вот такой код использовал, id записи передавал из процесса, в вашем варианте можно убрать проверку на id, т.к. будут обновляться детали на всех открытых страницах с подпиской:

        messages: {
            "RefreshMaterial": {
                "mode": Terrasoft.MessageMode.BROADCAST,
                "direction": Terrasoft.MessageDirectionType.SUBSCRIBE
            }
        },

 

			onEntityInitialized: function() {
				this.callParent(arguments);
				this.sandbox.subscribe("RefreshMaterial", this.reloadFromProcess, this);
			},
 
			reloadFromProcess: function(args) {
				if(args === this.get("Id")) {
					this.updateDetail({detail: "UsrMaterialDetail23d2c003", realoadAll: true});
				}
			},

 

Трефилов Павел Сергеевич,

А что использовать init или onEntityInitialized? В примере используют init. А у меня в methods уже был onEntityInitialized, для реализации другого функционала.

И как проверить работает оно или нет (я имею ввиду обновление реестра с использованием механизма отправки сообщений)? Записи в деталь с помощью только лишь БП и так нормально добавлялись.

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

Если смотреть пример, то там есть строка 

window.console.info("текст");

Для отладки тоже можете в методе добавить подобное, если после запуска процесса в консоле появился текст, то значит пришел сигнал из бп. Если нет, то где-то ошибка. Либо лучше научиться отладки js, ставить точку останова и т.п.

 

А обновление реестра работает или нет, чисто визуально определить. У вас же БП что-то делает, то значит после выполнения бп данные должны обновиться без перезагрузки страницы.

Трефилов Павел Сергеевич,

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

Обнаружил другую более существенную проблему. Если добавлять вручную записи в деталь нажимая на +, т.к. деталь с редактируемым реестром (при работе БП все хорошо), то появляется ошибка: Violation of PRIMARY KEY constraint 'PKOqfXc3lnQVBYwkElsuKFom04KY'. Cannot insert duplicate key in object 'dbo.UsrListWorks'. The duplicate key value is (9d4ea319-42ee-41b3-81ec-f556e4dc4517). The statement has been terminated. Не понятно почему, т.к. если посмотреть в базе данных, то детали с таким Id еще нет.

Pavel Litvinovich,

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

onSaved: function(response, config) {
if(this.isNew) {
config.isSilent;
}
this.callParent(arguments);
}
код не проверял на практике, но должен работать

По поду второй ошибки сложно судить, может где-то ошибка в коде детали

Трефилов Павел Сергеевич,

Спасибо за помощь!

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

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

 

Столкнулся с проблемой вызова 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;
}
Показать все комментарии